New qemu-based ioemu for fully virtualised guests.
Signed-off-by: Arun Sharma <arun.sharma@intel.com>
Signed-off-by: Keir Fraser <keir@xensource.com>
4273458dYPghQKVnj_xu5-fC38CcOg tools/gdb/gdb-6.2.1-xen-sparse/gdb/gdbserver/server.c
423d3a7b2ENk2IskDZYZ98pe5NsvIA tools/gdb/gdb-6.2.1-xen-sparse/mkbuildtree
423d3a7buANO_q-kgxIRffUu7lMnUw tools/gdb/gdbbuild
-41e2ff6dNPgvIrdIF6dC1azdex1U3A tools/ioemu/Makefile
-41e2ff6aoF5fgddZi0QpEWqFr89E5g tools/ioemu/font/vga.bitmap.h
-41e2ff6avgnBNvZRiL4ynyGGq2UKlw tools/ioemu/gui/Makefile
-41e2ff6a30Xuw7pDX3SlVBx3ssOMDQ tools/ioemu/gui/Makefile.in
-41e2ff6aGGn5D3-Yh856G7xWJ5ZJsA tools/ioemu/gui/bitmaps/cdromd.h
-41e2ff6abNiWU34DwftxJ30sI6TQmw tools/ioemu/gui/bitmaps/cdromd.xpm
-41e2ff6adSUYHlvyVpz7q1Izcx5_gQ tools/ioemu/gui/bitmaps/configbutton.h
-41e2ff6aLWWXfMqIH2jSCNUzuc4_Yg tools/ioemu/gui/bitmaps/configbutton.xpm
-41e2ff6ahsqMjwuhpbqfrFHCBqYhEA tools/ioemu/gui/bitmaps/copy.h
-41e2ff6ajL41CnUeGefMrNijudQlCg tools/ioemu/gui/bitmaps/copy.xpm
-41e2ff6aXn5GhkDNOGqUcfCLbDZf3w tools/ioemu/gui/bitmaps/floppya.h
-41e2ff6agOpnECodSZ62L-Uijy5fsQ tools/ioemu/gui/bitmaps/floppya.xpm
-41e2ff6akrHp6jG_Y2BmFpEcaswUqg tools/ioemu/gui/bitmaps/floppyb.h
-41e2ff6aGbvPO1cQLMLduGl16rntbg tools/ioemu/gui/bitmaps/floppyb.xpm
-41e2ff6aEcsgeBHQZ_5e3rfgo0USMA tools/ioemu/gui/bitmaps/mouse.h
-41e2ff6aO8pXESvDVxMG7TgZL7UvFA tools/ioemu/gui/bitmaps/mouse.xpm
-41e2ff6aSd1H6Z0dUVUYLsW-6EDrYw tools/ioemu/gui/bitmaps/paste.h
-41e2ff6aRGfY6Jd2TThqWtXoh2CHuQ tools/ioemu/gui/bitmaps/paste.xpm
-41e2ff6aKDap56ifPVgdBVPc9yfmvw tools/ioemu/gui/bitmaps/power.h
-41e2ff6aDLfEO8dFUd9IpsfUpMk-Vg tools/ioemu/gui/bitmaps/power.xpm
-41e2ff6aKWtTsWCds4vL2azV3w-XtQ tools/ioemu/gui/bitmaps/reset.h
-41e2ff6a_AU4_ytzHU0Btr3trcbVmA tools/ioemu/gui/bitmaps/reset.xpm
-41e2ff6a-hGpcXEChJQDo-xRyH5oGQ tools/ioemu/gui/bitmaps/snapshot.h
-41e2ff6aRoGi5nKyQFtcUzK0-9dRDA tools/ioemu/gui/bitmaps/snapshot.xpm
-41e2ff6aZdTp9lSJjyUI7YoXqQnCng tools/ioemu/gui/bitmaps/userbutton.h
-41e2ff6aWc4p23rAKngLMu8eLZiXlw tools/ioemu/gui/bitmaps/userbutton.xpm
-41e2ff6a7gMd57Q5DL0kRD-mR7JzZg tools/ioemu/gui/gui.cc
-41e2ff6a-USvofVXiSpY76RT4C0IVw tools/ioemu/gui/gui.h
-41e2ff6aYAuOb0x4zTVB7cWYIFIdOA tools/ioemu/gui/icon_bochs.h
-41e2ff6aZbFf-Djysg393N4vCEJ7ig tools/ioemu/gui/icon_bochs.xpm
-41e2ff6ai-vJcSE9hfz4SHZ20rK5QA tools/ioemu/gui/keymap.cc
-41e2ff6a_TY9EJnCcbr5EKV_pi90kg tools/ioemu/gui/keymap.h
-41e2ff6aP0co3DAK04MrugZCkp0roQ tools/ioemu/gui/keymaps/convertmap.pl
-41e2ff6a-GiP9bzqtVXEjxmxiYgzeg tools/ioemu/gui/keymaps/sdl-pc-de.map
-41e2ff6aa5xj7jyze5bcPnj-UHYgTQ tools/ioemu/gui/keymaps/sdl-pc-us.map
-41e2ff6ahemkf0kG8SzDXq8g2qp9Pg tools/ioemu/gui/keymaps/x11-pc-be.map
-41e2ff6ajdaBBS85yriZ3S9ecy5Odg tools/ioemu/gui/keymaps/x11-pc-da.map
-41e2ff6aGkLyRvwOTZnDqvobziAoiQ tools/ioemu/gui/keymaps/x11-pc-de.map
-41e2ff6aWcqOK6RjpY28Y4bVjMy9yg tools/ioemu/gui/keymaps/x11-pc-es.map
-41e2ff6aF46Uu09XOmmkcGDotToSxw tools/ioemu/gui/keymaps/x11-pc-fr.map
-41e2ff6aHM040MYLmOeW_PKIx1TWWg tools/ioemu/gui/keymaps/x11-pc-it.map
-41e2ff6aCa-6fHjBOoPWP8hDweZ1Fw tools/ioemu/gui/keymaps/x11-pc-se.map
-41e2ff6aUH4wvnqRwo91dJBnhxEYUg tools/ioemu/gui/keymaps/x11-pc-uk.map
-41e2ff6aF7b08llRJQBLgNAEfyn9wQ tools/ioemu/gui/keymaps/x11-pc-us.map
-41e2ff6a2gbWdoaE7X9vtizvQ4QqdQ tools/ioemu/gui/nogui.cc
-41e2ff6a_rWAWre2toEtNUMKliCJPA tools/ioemu/gui/rfb.cc
-41e2ff6aQfuugiO3YE07l03L6ASP9g tools/ioemu/gui/rfb.h
-41e2ff6aTWFzmW0sjxXpQq7ulaj_Pw tools/ioemu/gui/rfbproto.h
-41e2ff6bf4pfJkZTN5vA6HbiJJqeNA tools/ioemu/gui/sdl.h
-41e2ff6bVnojmIqKJCbhVUKtMcUWJg tools/ioemu/gui/sdlkeys.h
-41e2ff6bKVx97oSdGGToXQXvbQgkZA tools/ioemu/gui/siminterface.cc
-41e2ff6bDB5XABCVAA7nMolZPe5ZoA tools/ioemu/gui/siminterface.h
-41e2ff6benMg1o7HQ2C5PGS3KFHFow tools/ioemu/gui/svga.cc
-41e2ff6bz3XZGzzwvXGqFadb3QqWWQ tools/ioemu/gui/term.cc
-41e2ff6b8jzKgyKu2gNVlRWepPNA0A tools/ioemu/gui/textconfig.cc
-41e2ff6bUKaJhGtIDqUYzAesLg1MGA tools/ioemu/gui/textconfig.h
-41e2ff6b__Pd6Q2aYDZ5vB9bGJEMNA tools/ioemu/gui/x.cc
-41e2ff6bp96y5NyMIFjH-HpCRcGBPg tools/ioemu/include/bochs.h
-41e2ff6bqIMIJlitAnubjNjf70s3dw tools/ioemu/include/bxversion.h
-41e2ff6bTfksDlUXSWC_wC_g30r1cQ tools/ioemu/include/config.h
-41e2ff6bwDEGCUwYTf1oo9ZCva2nkw tools/ioemu/include/cpu/cpu.h
-41e2ff6bH1PTh2iMScpOn9v9R3SDag tools/ioemu/include/extplugin.h
-41e2ff6bFS9XP8ndI6IhGFitzsvTtw tools/ioemu/include/instrument.h
-41e2ff6bz71jKff_NUdmI279ArbMgw tools/ioemu/include/ltdl.h
-41e2ff6bYayW_YSVmb1sJCvk9z9-ug tools/ioemu/include/ltdlconf.h
-41e2ff6b_MdkIIjsFYTFMIKIt7Royw tools/ioemu/include/osdep.h
-41e2ff6bPJNSITgePniKtvlujrmcLA tools/ioemu/include/pc_system.h
-41e2ff6bmHZyZrzF7iHpD212GeAT-w tools/ioemu/include/plugin.h
-41e2ff6bHgstm2ZhCIdsag_c3_dVjA tools/ioemu/include/state_file.h
-41e2ff6bJjm8-4K6Cu2k6zoanQ8Yyg tools/ioemu/iodev/Makefile
-41e2ff6bKj9bQ4ELP2msSYoT7XrxHQ tools/ioemu/iodev/aspi-win32.h
-41e2ff6b95DLt3iA-okw7D4NJcaDCg tools/ioemu/iodev/biosdev.cc
-41e2ff6b1ra22hFnE6Tm9lxVaH4Mjw tools/ioemu/iodev/biosdev.h
-41e2ff6bftET40KQA19RAisCxyDHVQ tools/ioemu/iodev/cdrom.cc
-41e2ff6buuSLUZPj9EtlGA3tufslNQ tools/ioemu/iodev/cdrom.h
-41e2ff6bvD6jE2JHKP0wd7I_mB7MJg tools/ioemu/iodev/cdrom_beos.h
-41e2ff6b99qviTPyKLjy0-D5DIqACw tools/ioemu/iodev/cmos.cc
-41e2ff6bpeZbWqQfuwM_Xj-kElElAA tools/ioemu/iodev/cmos.h
-41e2ff6bRf7QN_i1c7BAzkQha8AFUg tools/ioemu/iodev/cpu.cc
-41e2ff6byVHp6G3fxAlly1u1sx_DEg tools/ioemu/iodev/crc32.cc
-41e2ff6bHWz28hOKgLKRizX9UjsyOQ tools/ioemu/iodev/crc32.h
-41e2ff6b3tvq7uKSC9DWkOswq0Re8w tools/ioemu/iodev/devices.cc
-41e2ff6bO-SYXzx1RB-1If_FNkyjLg tools/ioemu/iodev/dma.cc
-41e2ff6bdI7Ri1mVb1MzkvBKlNSx6Q tools/ioemu/iodev/dma.h
-41e2ff6bfnGRrb25sneyvOXxSi8pLg tools/ioemu/iodev/eth.cc
-41e2ff6bteOXqvNO1FIR5iFHUwqUuA tools/ioemu/iodev/eth.h
-41e2ff6bTQxXrfWSsDCISUAdzlAe9w tools/ioemu/iodev/eth_arpback.cc
-41e2ff6brorlh9N9Myd1_g7ktKcIfQ tools/ioemu/iodev/eth_fbsd.cc
-41e2ff6b5xRFy8_OISEtd2UrHEUdfw tools/ioemu/iodev/eth_linux.cc
-41e2ff6biySiByowEn40XP_yx_lxKg tools/ioemu/iodev/eth_null.cc
-41e2ff6bFAVD0UO_ob40usJOnEPAZg tools/ioemu/iodev/eth_packetmaker.cc
-41e2ff6bsR-mjksFNRC9HiDDVUfI2w tools/ioemu/iodev/eth_packetmaker.h
-41e2ff6bMnzZ7cpqVPQY0_0smpqjHw tools/ioemu/iodev/eth_tap.cc
-41e2ff6bGa18jj0cqoOAqBPDzk2Aog tools/ioemu/iodev/eth_tuntap.cc
-41e2ff6bY1u244mkTGfttym3HoLo5Q tools/ioemu/iodev/extfpuirq.cc
-41e2ff6b_wh3dgYBx38KIJ00Qv4XUA tools/ioemu/iodev/extfpuirq.h
-41e2ff6b3uiKo02slxJn11bvZKsF3g tools/ioemu/iodev/floppy.cc
-41e2ff6bKba0nlJHGy2kWUr_3e_nvw tools/ioemu/iodev/floppy.h
-41e2ff6bC1KaCAEBYYTkJJ5_pBydkQ tools/ioemu/iodev/gameport.cc
-41e2ff6bePGww4K0p8vTLphdE_zdig tools/ioemu/iodev/gameport.h
-41e2ff6biLQpMiiiKokz7qUXpBn5cg tools/ioemu/iodev/guest2host.h
-41e2ff6bji1Iix0CzQTeh9yB-Ao14Q tools/ioemu/iodev/harddrv.cc
-41e2ff6bcSDALK1SdvKvTCxemzpWwQ tools/ioemu/iodev/harddrv.h
-41e2ff6b36hFBfV06tX0a5CRjFpuxA tools/ioemu/iodev/ioapic.cc
-41e2ff6brajF6a0a7RkLHiX0M9oH7w tools/ioemu/iodev/ioapic.h
-41e2ff6btDX2IfOnC_LkP08ZlKxjJw tools/ioemu/iodev/iodebug.cc
-41e2ff6b-__Z4ECo9pHWVM-Rz-0ehw tools/ioemu/iodev/iodebug.h
-41e2ff6btRbGfsUt5k4MClieCZ-EBQ tools/ioemu/iodev/iodev.h
-41e2ff6bH5C9aG3f2QhoD6zCdShJYQ tools/ioemu/iodev/keyboard.cc
-41e2ff6bUOmeloSf5s9Gkdffo1bEyA tools/ioemu/iodev/keyboard.h
-41e2ff6b55oybF1yhInYSZX2bxiJSw tools/ioemu/iodev/load32bitOShack.cc
-41e2ff6b5WcmfYXaREzUm0KQu7pKCQ tools/ioemu/iodev/logio.cc
-41e2ff6bqqHfrDtizlRKA-_oPRbGAw tools/ioemu/iodev/main.cc
-41e2ff6cWAAGa6Pt6eE4URbCOq8wQA tools/ioemu/iodev/ne2k.cc
-41e2ff6cap6qrVL42AgTpxjav0QMQg tools/ioemu/iodev/ne2k.h
-41e2ff6cHH0UoJW74RKZFnPBSt1jUw tools/ioemu/iodev/osdep.cc
-41e2ff6ckuFNtxuAQDMVwJtYwL2QCg tools/ioemu/iodev/parallel.cc
-41e2ff6cbqWnJwLAQ9NDZJwUyGiIww tools/ioemu/iodev/parallel.h
-41e2ff6cAdkxmfzVhbQn9Plq3X4S_w tools/ioemu/iodev/pc_system.cc
-41e2ff6csu1e9S_rywWOq9B85IaZzA tools/ioemu/iodev/pci.cc
-41e2ff6cjcmNZLD17naGuKj_Qon6Ow tools/ioemu/iodev/pci.h
-41e2ff6c91zYiAb9XulXkl2vLERo-w tools/ioemu/iodev/pci2isa.cc
-41e2ff6cV7IdLNbFXwlWvdcOz4F1Aw tools/ioemu/iodev/pci2isa.h
-41e2ff6cviwF37ZllnYtHA3MEHRMWw tools/ioemu/iodev/pciusb.cc
-41e2ff6ceFmfyqr1MgYhEoRM1s6icQ tools/ioemu/iodev/pciusb.h
-41e2ff6cd-1VHyISVo789tv3ImNgLw tools/ioemu/iodev/pcivga.cc
-41e2ff6cVkXDlrNUTdt7D6BULEp1Tg tools/ioemu/iodev/pcivga.h
-41e2ff6c3xjAFB8X5OLFz_8Of62v2Q tools/ioemu/iodev/pic.cc
-41e2ff6c4UHzse5_N0Mx6u5dqKrVkw tools/ioemu/iodev/pic.h
-41e2ff6cdD9yovRmQNNJu8QVtZg7Iw tools/ioemu/iodev/pit.cc
-41e2ff6cXtvewmYJyoxrWGic2sOayg tools/ioemu/iodev/pit.h
-41e2ff6cXaqNRxMagdpNiT1kTWJJUA tools/ioemu/iodev/pit82c54.cc
-41e2ff6cHAkpKzMwyz3diMZWTswxmg tools/ioemu/iodev/pit82c54.h
-41e2ff6cMK9E2gjqHoWV9ZQfz-cP1Q tools/ioemu/iodev/pit_wrap.cc
-41e2ff6cbie7fPpQMgBImJ885GAPdw tools/ioemu/iodev/pit_wrap.h
-41e2ff6c0wLrWtBHxxboIzHsrZzkRA tools/ioemu/iodev/plugin.cc
-41e2ff6cN4Z6pnguPQaqiCkWp42MOQ tools/ioemu/iodev/scancodes.cc
-41e2ff6chK1sqb78l1sqhF3fJhjzBw tools/ioemu/iodev/scancodes.h
-41e2ff6cIyPvY7hNE5rP_PMZELhyVw tools/ioemu/iodev/scsi_commands.h
-41e2ff6cF3wH8A_66_yG92Wk7I2IWQ tools/ioemu/iodev/scsidefs.h
-41e2ff6cbAin6eD3Gfz2CozOS4_bwA tools/ioemu/iodev/scsipt.h
-41e2ff6cce6mNXZPGmlQ1bg_I0ef8Q tools/ioemu/iodev/serial.cc
-41e2ff6cxsITO-ikpd4vBYZUYO3qSw tools/ioemu/iodev/serial.h
-41e2ff6cbaCEgMJ92UELiRE2wEYe3g tools/ioemu/iodev/serial_raw.h
-41e2ff6cwDKTU8OukKNBNMDiAYUWvQ tools/ioemu/iodev/slowdown_timer.cc
-41e2ff6cM5XYdcgL417IBOzW-QipFg tools/ioemu/iodev/slowdown_timer.h
-41e2ff6c5X0WxdBPUyZlNmW6Zv_LRQ tools/ioemu/iodev/soundlnx.cc
-41e2ff6cIuE1VxGF_L6rdBtD6rZ_aA tools/ioemu/iodev/soundlnx.h
-41e2ff6cDIv87LKamP0Y-yjrdqALzQ tools/ioemu/iodev/soundwin.cc
-41e2ff6cB55j_uYIqYh-UiLS4wlm_g tools/ioemu/iodev/soundwin.h
-41e2ff6dRPBmtxjFbEM5WYuilnSSZg tools/ioemu/iodev/state_file.cc
-41e2ff6dMwkI1Dpa-UHSEzHCvjpOyw tools/ioemu/iodev/unmapped.cc
-41e2ff6d_yJMFHYPENtVmJz6wyldQA tools/ioemu/iodev/unmapped.h
-41e2ff6dU5hJI6Kn70mFingJo4cHUw tools/ioemu/iodev/vga.cc
-41e2ff6dh8xDcCXkZzpSqnFP-OXggw tools/ioemu/iodev/vga.h
-41e2ff6dayXwb5dxf0K5pd3q4QppRA tools/ioemu/iodev/virt_timer.cc
-41e2ff6dI_rNgBwki594UAWN337-zw tools/ioemu/iodev/virt_timer.h
-41e2ff6dCCtE_btrlEopLaCsLO3JDA tools/ioemu/memory/Makefile
-41e2ff6dZtwsTW8s-Gqv7bqObdvaXw tools/ioemu/memory/memory.cc
-41e2ff6dpk6EFzlHlsAsFEFdyG4wrA tools/ioemu/memory/memory.h
-41e2ff6d2i-wqgCe4iAXdckUc1GD-A tools/ioemu/memory/misc_mem.cc
-41e2ff6dCYuZgf6pxRmphkh5yeuA9Q tools/ioemu/mk/helix.mk
+428d0d82yOaUzYQuYQxH7VzQytKo-g tools/ioemu/COPYING
+428d0d82EdPp1TqJBembLgyB1y413w tools/ioemu/COPYING.LIB
+428d0d82fd6-QydvFfHmeQBGrKnrrA tools/ioemu/Changelog
+428d0d82xvTj4yzPYiurazyGj1PaEw tools/ioemu/Makefile
+428d0d82dUmXkgIy11G-hoKTkhvkfQ tools/ioemu/Makefile.target
+428d0d82HvgRPoyU3f60_u_t1L28Ag tools/ioemu/README
+428d0d820gXmfIVHub7p9VbT7bQcMw tools/ioemu/README.distrib
+428d0d82aoWewa_6Z5kNUTgkRw0wNg tools/ioemu/TODO
+428d0d82WYi8vrG7RKKyIJw01DAnGg tools/ioemu/VERSION
+428d0d82wB05ibBxTCSsAhz3qRO7Gg tools/ioemu/block-cloop.c
+428d0d82cucBBZFks3aMSL0-C3L9Nw tools/ioemu/block-cow.c
+428d0d82s5FM7xmnj1XLAMlt_DdRIA tools/ioemu/block-qcow.c
+428d0d83yWYa6mIH2mplo1L_3Cqadw tools/ioemu/block-vmdk.c
+428d0d83nfcgHvu37hviRYwAAAAxSQ tools/ioemu/block.c
+428d0d83LrXLfgm9h2RPNBRM_vkqsA tools/ioemu/block_int.h
+428d0d83zt7CgVsTa-CIorpIGVWe7g tools/ioemu/bswap.h
+428d0d83-I9bQJ8EduVO0OmP_YMtVg tools/ioemu/configure
+428d0d83sUjdDRZnfykBaWd_uGjVQQ tools/ioemu/console.c
+428d0d83Rsv-Pq8iGrvA0ChVTD-KEQ tools/ioemu/cpu-all.h
+428d0d830tCm2-QC3iLTo-yS2D7azQ tools/ioemu/cpu-defs.h
+428d0d83bOFEAX7Kc_lt7pm_ItnYOg tools/ioemu/cpu.h
+428d0d83wJqNCht75GfVfWqGzaDBGA tools/ioemu/create_keysym_header.sh
+428d0d83warJp9F3aKU4moRRVfTmFg tools/ioemu/exec-all.h
+428d0d83m3Kwp8vJKycK1n5a_LygfA tools/ioemu/exec.c
+428d0d83G-F1mvFyzCEMNhiU6ts8lQ tools/ioemu/hw/adb.c
+428d0d83EE1hpyfMfr667s4aFK42hg tools/ioemu/hw/adlib.c
+428d0d83AoBht7yFAmAUWoi-ZZS2Tw tools/ioemu/hw/cirrus_vga.c
+428d0d83lD5ovmJG_Q1VfIIjw1Fm-A tools/ioemu/hw/cirrus_vga_rop.h
+428d0d83SCwX65BPgonBcgYCxdKDNA tools/ioemu/hw/cirrus_vga_rop2.h
+428d0d83zAKLZ8JX7_D6RMGcml3jRA tools/ioemu/hw/cuda.c
+428d0d83OLV-aQor-LfByakKvo-1-g tools/ioemu/hw/dma.c
+428d0d83P1VkKtXn90RMN8eBsvPFQA tools/ioemu/hw/fdc.c
+428d0d849AqxX6FsPHv0ovjaFyNMVg tools/ioemu/hw/fmopl.c
+428d0d84-hHRu7PVXjfc7oLfrDxY6g tools/ioemu/hw/fmopl.h
+428d0d84zbtT2C8Xci_SqMP5bZ-wcQ tools/ioemu/hw/i8254.c
+428d0d84KlR61OwSzjF0-L4iz58dfQ tools/ioemu/hw/i8259.c
+428d0d84auhZx6c5Kv3WrfM2UZvqHA tools/ioemu/hw/ide.c
+428d0d84WSlhNzdrcb-f-Lg-W9dniQ tools/ioemu/hw/iommu.c
+428d0d84ri8ZtvhB6RJr1YNejjNWIQ tools/ioemu/hw/lance.c
+428d0d84cxFFgDv5fBFrlxGoCiy6Nw tools/ioemu/hw/m48t08.c
+428d0d84MQYDhAOLnBnag1BZWcW6JA tools/ioemu/hw/m48t08.h
+428d0d84sE4ghX33RQ5kDSuyoLdhFg tools/ioemu/hw/m48t59.c
+428d0d8465kZWTT4mVgf-VonglDOxw tools/ioemu/hw/m48t59.h
+428d0d84OY7tvE-PKrBfjf2vEQXyMA tools/ioemu/hw/magic-load.c
+428d0d84U-PYPR_GMVJoQsbCAVAQow tools/ioemu/hw/mc146818rtc.c
+428d0d84jtSXGjQYKd_xvSiMM4C_7Q tools/ioemu/hw/ne2000.c
+428d0d84SMHPk0cRnrZgUYkMxFXMMQ tools/ioemu/hw/openpic.c
+428d0d84lyG0XDg5MxLMSee3MWgq3g tools/ioemu/hw/pc.c
+428d0d84HWR3Q7dEESycfJ7hSWdGig tools/ioemu/hw/pci.c
+428d0d84Noyn4ik0UX1E7OdfuFdrIw tools/ioemu/hw/pckbd.c
+428d0d840SMURRjsz9V96rwt-naynw tools/ioemu/hw/ppc.c
+428d0d84MI7kZftH_c0FK1qiiyQBZg tools/ioemu/hw/ppc_chrp.c
+428d0d859-xwA89jmzFk6x9UyXjAeA tools/ioemu/hw/ppc_prep.c
+428d0d85YS1n4Fr_EK7B01EWSmrYRg tools/ioemu/hw/sb16.c
+428d0d85GrUXL_p0ppOUIfWf8--hvw tools/ioemu/hw/sched.c
+428d0d85wP3aLdHYJ-hDAImDP2sj_g tools/ioemu/hw/serial.c
+428d0d85mOfwFqDCO76K6bc4IQOxQA tools/ioemu/hw/sun4m.c
+428d0d852OCpAsfS1PNoJOfnHhFPSQ tools/ioemu/hw/tcx.c
+428d0d85gCUCX0nbuRAt28QJgQ5P8w tools/ioemu/hw/timer.c
+428d0d85hp-zgN40hVYXWRjhInkUkg tools/ioemu/hw/vga.c
+428d0d85G_4S-hpRyrhV4yGjSrS-cQ tools/ioemu/hw/vga_int.h
+428d0d85oWl1ONX_gIZWS1fXjeXGlA tools/ioemu/hw/vga_template.h
+428d0d85-wAtLF5FYFHCUAxXKNbEkA tools/ioemu/i386-vl.ld
+428d0d85d831iQvvCD3LcaOD9rYGkg tools/ioemu/i386.ld
+428d0d85_mNnFPE8hnoC3VvBD9CCuA tools/ioemu/keyboard_rdesktop.c
+428d0d85SyOIeDg3SoxH2BiBpXWWkA tools/ioemu/keymaps/ar
+428d0d85ToGTVvPrl8hKAi2QxCzp2w tools/ioemu/keymaps/common
+428d0d85fmdxRplWI5Jp54NNZy5Mmw tools/ioemu/keymaps/convert-map
+428d0d85t5IBwlnttPreCS0UX3nbOw tools/ioemu/keymaps/da
+428d0d85XRNojuUlkCgvea0I_fdJEg tools/ioemu/keymaps/de
+428d0d85QPup3ixECEpa7Pzr9lLEyw tools/ioemu/keymaps/de-ch
+428d0d86r5UpNhOSALGJUUDaGv-vnQ tools/ioemu/keymaps/en-gb
+428d0d86ylUT-4Skjnwa27vxIeBqYw tools/ioemu/keymaps/en-us
+428d0d86vcHusn3XzWTLjKLDdNhZxw tools/ioemu/keymaps/es
+428d0d86UVS0Km-9J94RAQM7iAbBzw tools/ioemu/keymaps/et
+428d0d86hS47OlX4USgPPWk6RFWKLQ tools/ioemu/keymaps/fi
+428d0d86kOcjaVVZqDgV2JDGcXQ8rg tools/ioemu/keymaps/fo
+428d0d86c4GgMp1hDU2MFxiZ1Pz9Lg tools/ioemu/keymaps/fr
+428d0d86BdbSM5PxuMaSf8vBv6rXQg tools/ioemu/keymaps/fr-be
+428d0d86dQk_p9io2QdI9SGC6FVidg tools/ioemu/keymaps/fr-ca
+428d0d86JpfLBZmnrv7Yp0tuezgzng tools/ioemu/keymaps/fr-ch
+428d0d861RURctgJ3cgtnq0chW6JOA tools/ioemu/keymaps/hr
+428d0d86mqzqw70FkLHZFzIkvTJBpw tools/ioemu/keymaps/hu
+428d0d86O3ruSBL8ZyRBeLF7Ow67Og tools/ioemu/keymaps/is
+428d0d87pcCatuZLYpVWtUu2Da9sgw tools/ioemu/keymaps/it
+428d0d87M3Hy7ubCu27ZO-zWDk-YhQ tools/ioemu/keymaps/ja
+428d0d87CqrbJBUI28UxJCIduSJ4rQ tools/ioemu/keymaps/lt
+428d0d87jIV_V1YwET59i-Py3h0ILA tools/ioemu/keymaps/lv
+428d0d87T3KIxrywXSAkRu-AiQQgIQ tools/ioemu/keymaps/mk
+428d0d87_wmWi_IBHfpmZzhCKU-Baw tools/ioemu/keymaps/modifiers
+428d0d87GgUuEd4Mz9p3mUGkdMdOsg tools/ioemu/keymaps/nl
+428d0d87E1NtUwguKl72ifCTjDQ5rQ tools/ioemu/keymaps/nl-be
+428d0d87lKhQOfn5yQ0tq3u7hfIgpw tools/ioemu/keymaps/no
+428d0d87iD3aff-LOlaA4CmOUVct3Q tools/ioemu/keymaps/pl
+428d0d870CMCzI7c6gcGZMNuIYGbnQ tools/ioemu/keymaps/pt
+428d0d87gCs2M4A4P1ITzW86lm_-JA tools/ioemu/keymaps/pt-br
+428d0d87nzQ8eK1b9_Zs1Z82dOuX1Q tools/ioemu/keymaps/ru
+428d0d87uHdsh15a5mAD-HyWni8QDw tools/ioemu/keymaps/sl
+428d0d87gsUMIP42oFecYrdZAJDAuw tools/ioemu/keymaps/sv
+428d0d87OcfLjKuhg6p2uuiAPvJBqQ tools/ioemu/keymaps/th
+428d0d87QbRtHJUft9qBkNXcl4pbzw tools/ioemu/keymaps/tr
+428d0d88CJoMejkmBh6pWaqKMvQF8A tools/ioemu/main.c
+428d0d88Fcan7gQZ6axXOmokBDLe7g tools/ioemu/monitor.c
+428d0d88lVaOC64YBZ1Wzt-WV4JaSw tools/ioemu/osdep.c
+428d0d885W7r27CDEJCW6Jlbxggc9g tools/ioemu/osdep.h
+428d0d88CiP9tVdIdLWAzOnCOSdafg tools/ioemu/path.c
+428d0d88jzHltLAzyhV1lpFckzy8CA tools/ioemu/pc-bios/Makefile
+428d0d889pv_iPNBFn6cNRzQfJMC3A tools/ioemu/pc-bios/README
+428d0d88mhWW8SQFNfp-NaH3c8QQkg tools/ioemu/pc-bios/bios.bin
+428d0d88LMSMDbTFG1-sS8LL90hExw tools/ioemu/pc-bios/bios.diff
+428d0d89SHpdZE1S-ywjJCulIWs4Ag tools/ioemu/pc-bios/linux_boot.S
+428d0d89hiL0UgU71ero86GEu1loaA tools/ioemu/pc-bios/linux_boot.bin
+428d0d894MKpOb385vcoB_s_4q0QOA tools/ioemu/pc-bios/ppc_rom.bin
+428d0d896uo6qr-ONYkpleolayT4zw tools/ioemu/pc-bios/proll.bin
+428d0d893gsF8AcCadeYXcKM-aqssA tools/ioemu/pc-bios/proll.patch
+428d0d89GgbrVx4Ov3Zg-SFX_0BRdw tools/ioemu/pc-bios/vgabios-cirrus.bin
+428d0d89h9nqxPIgDpPMXZIWkdosNw tools/ioemu/pc-bios/vgabios.bin
+428d0d8908B65zMmhdGVME3jv7gpww tools/ioemu/qemu-binfmt-conf.sh
+428d0d89eKfKJmNEURTxLUtIjclvDw tools/ioemu/qemu-doc.html
+428d0d89jF9HlGboO7nLco-tqjLJqQ tools/ioemu/qemu-doc.texi
+428d0d89taY6NPlnIyOAMQd_Ww5qUw tools/ioemu/qemu-img.c
+428d0d89uGqd5VkBf5j3HFIkQMxsNA tools/ioemu/qemu-mkcow.1
+428d0d8941iGGM85zXzn4wSj6zgbQg tools/ioemu/qemu-tech.html
+428d0d89IkHVfdVTilpTpxDvOCOiIw tools/ioemu/qemu-tech.texi
+428d0d89ME4klwpFGjbiKXQrj2KF7A tools/ioemu/qemu.1
+428d0d89FY-g4UPH-ZW7t5ZCqvQVTQ tools/ioemu/readline.c
+428d0d89dLURbktZFufDKSHan01GFg tools/ioemu/sdl.c
+428d0d8atdIE_8ACJPPii5_asQNafw tools/ioemu/target-i386-dm/device-model
+428d0d8ahpRAYl6s_itBxnTcxyMHaQ tools/ioemu/target-i386-dm/helper2.c
+428d0d8aU3Moaq4zNW5QMV_NxD-4XA tools/ioemu/target-i386-dm/qemu-ifup
+428d0d8aqidj8n5H2_2qhBV0mIIJzA tools/ioemu/target-i386-dm/qemu-vgaram-bin.gz
+428d0d8ahJ-jctJYDXyAMh91-ifrmg tools/ioemu/tests/Makefile
+428d0d8ax12h3Jd3Vhw4nh-eG99-iQ tools/ioemu/tests/hello-arm.c
+428d0d8acsBcsGQPd0qQllU-4c9fXw tools/ioemu/tests/hello-i386.c
+428d0d8aSEf5Q4wB3iaEThUssfFH8w tools/ioemu/tests/linux-test.c
+428d0d8a_orWq4Mg5EasDj2l6f4a0w tools/ioemu/tests/pi_10.com
+428d0d8aBv9VBjblSU8iAaVojF4qqw tools/ioemu/tests/qruncom.c
+428d0d8az-0qSZDA45Mt6y2SdsqF4w tools/ioemu/tests/runcom.c
+428d0d8aSf3jnF_aFvwAemDeROZcKQ tools/ioemu/tests/sha1.c
+428d0d8aBZGfRZ662SQIuXLdpmih0w tools/ioemu/tests/test-i386-code16.S
+428d0d8a8DbLZWzSyVQ_wX1RGr9SVQ tools/ioemu/tests/test-i386-muldiv.h
+428d0d8aaMQbnc_vqyQyOcUzyVrXyg tools/ioemu/tests/test-i386-shift.h
+428d0d8aKYkFtFSCFHFUivErvx0iqg tools/ioemu/tests/test-i386-vm86.S
+428d0d8aHx2CzT77VEsXouep7lZaYQ tools/ioemu/tests/test-i386.c
+428d0d8aDSIoqxC4_zr2z8vxMKrmeA tools/ioemu/tests/test-i386.h
+428d0d8ajPT5QfGuunOvjNibmURtqQ tools/ioemu/tests/test_path.c
+428d0d8bPccWrah4Y_zICBNZ5exhDw tools/ioemu/tests/testthread.c
+428d0d8b5F7EB4JnUbdTi_SZvF2wXg tools/ioemu/texi2pod.pl
+428d0d8bMq0ZpccpHb1iVvSNbJjRxg tools/ioemu/thunk.c
+428d0d8b2PYfwKLLShlnWcM3VWq9ag tools/ioemu/thunk.h
+428d0d8bfvbYQwj6MgDr958m4_SfRA tools/ioemu/vgafont.h
+428d0d8bgAojEQcAcTV2gj2E_eG4Lw tools/ioemu/vl.c
+428d0d8bXiCY4iTjoSPxGry8jXdAtg tools/ioemu/vl.h
+428d0d8bQVKedvN5EIPm39s33TXkpA tools/ioemu/vnc.c
3fbba6dbDfYvJSsw9500b4SZyUhxjQ tools/libxc/Makefile
41dde8afKYRKxS4XtLv1KUegGQy_bg tools/libxc/linux_boot_params.h
41cc934abX-QLXJXW_clV_wRjM0zYg tools/libxc/plan9a.out.h
SUBDIRS += python
SUBDIRS += xfrd
SUBDIRS += xcs
-ifndef XEN_NO_IOEMU
-SUBDIRS += ioemu
-endif
SUBDIRS += pygrub
-.PHONY: all install clean check check_clean
+.PHONY: all install clean check check_clean ioemu eioemuinstall ioemuclean
+
+ifndef XEN_NO_IOEMU
+ioemu ioemuinstall ioemuclean:
+ [ -f ioemu/config-host.h ] || \
+ (cd ioemu; ./configure --prefix=$(DESTDIR)/usr)
+ $(MAKE) -C ioemu $(patsubst ioemu%,%,$@)
+else
+ioemu ioemuinstall ioemuclean:
+endif
all: check
@set -e; for subdir in $(SUBDIRS); do \
- if [ -f $$subdir/configure ]; then \
- (cd $$subdir; ./configure --prefix=$(DESTDIR)/usr) \
- fi; \
$(MAKE) -C $$subdir $@; \
done
+ $(MAKE) ioemu
install: check
@set -e; for subdir in $(SUBDIRS); do \
$(MAKE) -C $$subdir $@; \
done
+ $(MAKE) ioemuinstall
clean: check_clean
@set -e; for subdir in $(SUBDIRS); do \
$(MAKE) -C $$subdir $@; \
done
+ $(MAKE) ioemuclean
check:
$(MAKE) -C check
--- /dev/null
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+ 675 Mass Ave, Cambridge, MA 02139, USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+\f
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+\f
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+\f
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+\f
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+\f
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) 19yy <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) 19yy name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Library General
+Public License instead of this License.
--- /dev/null
+ GNU LESSER GENERAL PUBLIC LICENSE
+ Version 2.1, February 1999
+
+ Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+ 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+[This is the first released version of the Lesser GPL. It also counts
+ as the successor of the GNU Library Public License, version 2, hence
+ the version number 2.1.]
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+Licenses are intended to guarantee your freedom to share and change
+free software--to make sure the software is free for all its users.
+
+ This license, the Lesser General Public License, applies to some
+specially designated software packages--typically libraries--of the
+Free Software Foundation and other authors who decide to use it. You
+can use it too, but we suggest you first think carefully about whether
+this license or the ordinary General Public License is the better
+strategy to use in any particular case, based on the explanations below.
+
+ When we speak of free software, we are referring to freedom of use,
+not price. Our General Public Licenses are designed to make sure that
+you have the freedom to distribute copies of free software (and charge
+for this service if you wish); that you receive source code or can get
+it if you want it; that you can change the software and use pieces of
+it in new free programs; and that you are informed that you can do
+these things.
+
+ To protect your rights, we need to make restrictions that forbid
+distributors to deny you these rights or to ask you to surrender these
+rights. These restrictions translate to certain responsibilities for
+you if you distribute copies of the library or if you modify it.
+
+ For example, if you distribute copies of the library, whether gratis
+or for a fee, you must give the recipients all the rights that we gave
+you. You must make sure that they, too, receive or can get the source
+code. If you link other code with the library, you must provide
+complete object files to the recipients, so that they can relink them
+with the library after making changes to the library and recompiling
+it. And you must show them these terms so they know their rights.
+
+ We protect your rights with a two-step method: (1) we copyright the
+library, and (2) we offer you this license, which gives you legal
+permission to copy, distribute and/or modify the library.
+
+ To protect each distributor, we want to make it very clear that
+there is no warranty for the free library. Also, if the library is
+modified by someone else and passed on, the recipients should know
+that what they have is not the original version, so that the original
+author's reputation will not be affected by problems that might be
+introduced by others.
+\f
+ Finally, software patents pose a constant threat to the existence of
+any free program. We wish to make sure that a company cannot
+effectively restrict the users of a free program by obtaining a
+restrictive license from a patent holder. Therefore, we insist that
+any patent license obtained for a version of the library must be
+consistent with the full freedom of use specified in this license.
+
+ Most GNU software, including some libraries, is covered by the
+ordinary GNU General Public License. This license, the GNU Lesser
+General Public License, applies to certain designated libraries, and
+is quite different from the ordinary General Public License. We use
+this license for certain libraries in order to permit linking those
+libraries into non-free programs.
+
+ When a program is linked with a library, whether statically or using
+a shared library, the combination of the two is legally speaking a
+combined work, a derivative of the original library. The ordinary
+General Public License therefore permits such linking only if the
+entire combination fits its criteria of freedom. The Lesser General
+Public License permits more lax criteria for linking other code with
+the library.
+
+ We call this license the "Lesser" General Public License because it
+does Less to protect the user's freedom than the ordinary General
+Public License. It also provides other free software developers Less
+of an advantage over competing non-free programs. These disadvantages
+are the reason we use the ordinary General Public License for many
+libraries. However, the Lesser license provides advantages in certain
+special circumstances.
+
+ For example, on rare occasions, there may be a special need to
+encourage the widest possible use of a certain library, so that it becomes
+a de-facto standard. To achieve this, non-free programs must be
+allowed to use the library. A more frequent case is that a free
+library does the same job as widely used non-free libraries. In this
+case, there is little to gain by limiting the free library to free
+software only, so we use the Lesser General Public License.
+
+ In other cases, permission to use a particular library in non-free
+programs enables a greater number of people to use a large body of
+free software. For example, permission to use the GNU C Library in
+non-free programs enables many more people to use the whole GNU
+operating system, as well as its variant, the GNU/Linux operating
+system.
+
+ Although the Lesser General Public License is Less protective of the
+users' freedom, it does ensure that the user of a program that is
+linked with the Library has the freedom and the wherewithal to run
+that program using a modified version of the Library.
+
+ The precise terms and conditions for copying, distribution and
+modification follow. Pay close attention to the difference between a
+"work based on the library" and a "work that uses the library". The
+former contains code derived from the library, whereas the latter must
+be combined with the library in order to run.
+\f
+ GNU LESSER GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License Agreement applies to any software library or other
+program which contains a notice placed by the copyright holder or
+other authorized party saying it may be distributed under the terms of
+this Lesser General Public License (also called "this License").
+Each licensee is addressed as "you".
+
+ A "library" means a collection of software functions and/or data
+prepared so as to be conveniently linked with application programs
+(which use some of those functions and data) to form executables.
+
+ The "Library", below, refers to any such software library or work
+which has been distributed under these terms. A "work based on the
+Library" means either the Library or any derivative work under
+copyright law: that is to say, a work containing the Library or a
+portion of it, either verbatim or with modifications and/or translated
+straightforwardly into another language. (Hereinafter, translation is
+included without limitation in the term "modification".)
+
+ "Source code" for a work means the preferred form of the work for
+making modifications to it. For a library, complete source code means
+all the source code for all modules it contains, plus any associated
+interface definition files, plus the scripts used to control compilation
+and installation of the library.
+
+ Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running a program using the Library is not restricted, and output from
+such a program is covered only if its contents constitute a work based
+on the Library (independent of the use of the Library in a tool for
+writing it). Whether that is true depends on what the Library does
+and what the program that uses the Library does.
+
+ 1. You may copy and distribute verbatim copies of the Library's
+complete source code as you receive it, in any medium, provided that
+you conspicuously and appropriately publish on each copy an
+appropriate copyright notice and disclaimer of warranty; keep intact
+all the notices that refer to this License and to the absence of any
+warranty; and distribute a copy of this License along with the
+Library.
+
+ You may charge a fee for the physical act of transferring a copy,
+and you may at your option offer warranty protection in exchange for a
+fee.
+\f
+ 2. You may modify your copy or copies of the Library or any portion
+of it, thus forming a work based on the Library, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) The modified work must itself be a software library.
+
+ b) You must cause the files modified to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ c) You must cause the whole of the work to be licensed at no
+ charge to all third parties under the terms of this License.
+
+ d) If a facility in the modified Library refers to a function or a
+ table of data to be supplied by an application program that uses
+ the facility, other than as an argument passed when the facility
+ is invoked, then you must make a good faith effort to ensure that,
+ in the event an application does not supply such function or
+ table, the facility still operates, and performs whatever part of
+ its purpose remains meaningful.
+
+ (For example, a function in a library to compute square roots has
+ a purpose that is entirely well-defined independent of the
+ application. Therefore, Subsection 2d requires that any
+ application-supplied function or table used by this function must
+ be optional: if the application does not supply it, the square
+ root function must still compute square roots.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Library,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Library, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote
+it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Library.
+
+In addition, mere aggregation of another work not based on the Library
+with the Library (or with a work based on the Library) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may opt to apply the terms of the ordinary GNU General Public
+License instead of this License to a given copy of the Library. To do
+this, you must alter all the notices that refer to this License, so
+that they refer to the ordinary GNU General Public License, version 2,
+instead of to this License. (If a newer version than version 2 of the
+ordinary GNU General Public License has appeared, then you can specify
+that version instead if you wish.) Do not make any other change in
+these notices.
+\f
+ Once this change is made in a given copy, it is irreversible for
+that copy, so the ordinary GNU General Public License applies to all
+subsequent copies and derivative works made from that copy.
+
+ This option is useful when you wish to copy part of the code of
+the Library into a program that is not a library.
+
+ 4. You may copy and distribute the Library (or a portion or
+derivative of it, under Section 2) in object code or executable form
+under the terms of Sections 1 and 2 above provided that you accompany
+it with the complete corresponding machine-readable source code, which
+must be distributed under the terms of Sections 1 and 2 above on a
+medium customarily used for software interchange.
+
+ If distribution of object code is made by offering access to copy
+from a designated place, then offering equivalent access to copy the
+source code from the same place satisfies the requirement to
+distribute the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 5. A program that contains no derivative of any portion of the
+Library, but is designed to work with the Library by being compiled or
+linked with it, is called a "work that uses the Library". Such a
+work, in isolation, is not a derivative work of the Library, and
+therefore falls outside the scope of this License.
+
+ However, linking a "work that uses the Library" with the Library
+creates an executable that is a derivative of the Library (because it
+contains portions of the Library), rather than a "work that uses the
+library". The executable is therefore covered by this License.
+Section 6 states terms for distribution of such executables.
+
+ When a "work that uses the Library" uses material from a header file
+that is part of the Library, the object code for the work may be a
+derivative work of the Library even though the source code is not.
+Whether this is true is especially significant if the work can be
+linked without the Library, or if the work is itself a library. The
+threshold for this to be true is not precisely defined by law.
+
+ If such an object file uses only numerical parameters, data
+structure layouts and accessors, and small macros and small inline
+functions (ten lines or less in length), then the use of the object
+file is unrestricted, regardless of whether it is legally a derivative
+work. (Executables containing this object code plus portions of the
+Library will still fall under Section 6.)
+
+ Otherwise, if the work is a derivative of the Library, you may
+distribute the object code for the work under the terms of Section 6.
+Any executables containing that work also fall under Section 6,
+whether or not they are linked directly with the Library itself.
+\f
+ 6. As an exception to the Sections above, you may also combine or
+link a "work that uses the Library" with the Library to produce a
+work containing portions of the Library, and distribute that work
+under terms of your choice, provided that the terms permit
+modification of the work for the customer's own use and reverse
+engineering for debugging such modifications.
+
+ You must give prominent notice with each copy of the work that the
+Library is used in it and that the Library and its use are covered by
+this License. You must supply a copy of this License. If the work
+during execution displays copyright notices, you must include the
+copyright notice for the Library among them, as well as a reference
+directing the user to the copy of this License. Also, you must do one
+of these things:
+
+ a) Accompany the work with the complete corresponding
+ machine-readable source code for the Library including whatever
+ changes were used in the work (which must be distributed under
+ Sections 1 and 2 above); and, if the work is an executable linked
+ with the Library, with the complete machine-readable "work that
+ uses the Library", as object code and/or source code, so that the
+ user can modify the Library and then relink to produce a modified
+ executable containing the modified Library. (It is understood
+ that the user who changes the contents of definitions files in the
+ Library will not necessarily be able to recompile the application
+ to use the modified definitions.)
+
+ b) Use a suitable shared library mechanism for linking with the
+ Library. A suitable mechanism is one that (1) uses at run time a
+ copy of the library already present on the user's computer system,
+ rather than copying library functions into the executable, and (2)
+ will operate properly with a modified version of the library, if
+ the user installs one, as long as the modified version is
+ interface-compatible with the version that the work was made with.
+
+ c) Accompany the work with a written offer, valid for at
+ least three years, to give the same user the materials
+ specified in Subsection 6a, above, for a charge no more
+ than the cost of performing this distribution.
+
+ d) If distribution of the work is made by offering access to copy
+ from a designated place, offer equivalent access to copy the above
+ specified materials from the same place.
+
+ e) Verify that the user has already received a copy of these
+ materials or that you have already sent this user a copy.
+
+ For an executable, the required form of the "work that uses the
+Library" must include any data and utility programs needed for
+reproducing the executable from it. However, as a special exception,
+the materials to be distributed need not include anything that is
+normally distributed (in either source or binary form) with the major
+components (compiler, kernel, and so on) of the operating system on
+which the executable runs, unless that component itself accompanies
+the executable.
+
+ It may happen that this requirement contradicts the license
+restrictions of other proprietary libraries that do not normally
+accompany the operating system. Such a contradiction means you cannot
+use both them and the Library together in an executable that you
+distribute.
+\f
+ 7. You may place library facilities that are a work based on the
+Library side-by-side in a single library together with other library
+facilities not covered by this License, and distribute such a combined
+library, provided that the separate distribution of the work based on
+the Library and of the other library facilities is otherwise
+permitted, and provided that you do these two things:
+
+ a) Accompany the combined library with a copy of the same work
+ based on the Library, uncombined with any other library
+ facilities. This must be distributed under the terms of the
+ Sections above.
+
+ b) Give prominent notice with the combined library of the fact
+ that part of it is a work based on the Library, and explaining
+ where to find the accompanying uncombined form of the same work.
+
+ 8. You may not copy, modify, sublicense, link with, or distribute
+the Library except as expressly provided under this License. Any
+attempt otherwise to copy, modify, sublicense, link with, or
+distribute the Library is void, and will automatically terminate your
+rights under this License. However, parties who have received copies,
+or rights, from you under this License will not have their licenses
+terminated so long as such parties remain in full compliance.
+
+ 9. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Library or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Library (or any work based on the
+Library), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Library or works based on it.
+
+ 10. Each time you redistribute the Library (or any work based on the
+Library), the recipient automatically receives a license from the
+original licensor to copy, distribute, link with or modify the Library
+subject to these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties with
+this License.
+\f
+ 11. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Library at all. For example, if a patent
+license would not permit royalty-free redistribution of the Library by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Library.
+
+If any portion of this section is held invalid or unenforceable under any
+particular circumstance, the balance of the section is intended to apply,
+and the section as a whole is intended to apply in other circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 12. If the distribution and/or use of the Library is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Library under this License may add
+an explicit geographical distribution limitation excluding those countries,
+so that distribution is permitted only in or among countries not thus
+excluded. In such case, this License incorporates the limitation as if
+written in the body of this License.
+
+ 13. The Free Software Foundation may publish revised and/or new
+versions of the Lesser General Public License from time to time.
+Such new versions will be similar in spirit to the present version,
+but may differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Library
+specifies a version number of this License which applies to it and
+"any later version", you have the option of following the terms and
+conditions either of that version or of any later version published by
+the Free Software Foundation. If the Library does not specify a
+license version number, you may choose any version ever published by
+the Free Software Foundation.
+\f
+ 14. If you wish to incorporate parts of the Library into other free
+programs whose distribution conditions are incompatible with these,
+write to the author to ask for permission. For software which is
+copyrighted by the Free Software Foundation, write to the Free
+Software Foundation; we sometimes make exceptions for this. Our
+decision will be guided by the two goals of preserving the free status
+of all derivatives of our free software and of promoting the sharing
+and reuse of software generally.
+
+ NO WARRANTY
+
+ 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+
+ 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+\f
+ How to Apply These Terms to Your New Libraries
+
+ If you develop a new library, and you want it to be of the greatest
+possible use to the public, we recommend making it free software that
+everyone can redistribute and change. You can do so by permitting
+redistribution under these terms (or, alternatively, under the terms of the
+ordinary General Public License).
+
+ To apply these terms, attach the following notices to the library. It is
+safest to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the library's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+Also add information on how to contact you by electronic and paper mail.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the library, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the
+ library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+
+ <signature of Ty Coon>, 1 April 1990
+ Ty Coon, President of Vice
+
+That's all there is to it!
+
+
--- /dev/null
+version 0.6.1:
+
+ - Mac OS X port (Pierre d'Herbemont)
+ - Virtual console support
+ - Better monitor line edition
+ - New block device layer
+ - New 'qcow' growable disk image support with AES encryption and
+ transparent decompression
+ - VMware 3 and 4 read-only disk image support (untested)
+ - Support for up to 4 serial ports
+ - TFTP server support (Magnus Damm)
+ - Port redirection support in user mode networking
+ - Support for not executable data sections
+ - Compressed loop disk image support (Johannes Schindelin)
+ - Level triggered IRQ fix (aka NE2000 PCI performance fix) (Steve
+ Wormley)
+ - Fixed Fedora Core 2 problems (now you can run qemu without any
+ LD_ASSUME_KERNEL tricks on FC2)
+ - DHCP fix for Windows (accept DHCPREQUEST alone)
+ - SPARC system emulation (Blue Swirl)
+ - Automatic Samba configuration for host file access from Windows.
+ - '-loadvm' and '-full-screen' options
+ - ne2000 savevm support (Johannes Schindelin)
+ - Ctrl-Alt is now the default grab key. Ctrl-Alt-[0-9] switches to
+ the virtual consoles.
+ - BIOS floppy fix for NT4 (Mike Nordell, Derek Fawcus, Volker Ruppert)
+ - Floppy fixes for NT4 and NT5 (Mike Nordell)
+ - NT4 IDE fixes (Ben Pfaf, Mike Nordell)
+ - SDL Audio support and SB16 fixes (malc)
+ - ENTER instruction bug fix (initial patch by Stefan Kisdaroczi)
+ - VGA font change fix
+ - VGA read-only CRTC register fix
+
+version 0.6.0:
+
+ - minimalist FPU exception support (NetBSD FPU probe fix)
+ - cr0.ET fix (Win95 boot)
+ - *BSD port (Markus Niemisto)
+ - I/O access fix (signaled by Mark Jonckheere)
+ - IDE drives serial number fix (Mike Nordell)
+ - int13 CDROM BIOS fix (aka Solaris x86 install CD fix)
+ - int15, ah=86 BIOS fix (aka Solaris x86 hardware probe hang up fix)
+ - BSR/BSF "undefined behaviour" fix
+ - vmdk2raw: convert VMware disk images to raw images
+ - PCI support
+ - NE2K PCI support
+ - dummy VGA PCI support
+ - VGA font selection fix (Daniel Serpell)
+ - PIC reset fix (Hidemi KAWAI)
+ - PIC spurious irq support (aka Solaris install bug)
+ - added '-localtime' option
+ - Cirrus CL-GD54xx VGA support (initial patch by Makoto Suzuki (suzu))
+ - APM and system shutdown support
+ - Fixed system reset
+ - Support for other PC BIOSes
+ - Initial PowerMac hardware emulation
+ - PowerMac/PREP OpenFirmware compatible BIOS (Jocelyn Mayer)
+ - initial IDE BMDMA support (needed for Darwin x86)
+ - Set the default memory size for PC emulation to 128 MB
+
+version 0.5.5:
+
+ - SDL full screen support (initial patch by malc)
+ - VGA support on PowerPC PREP
+ - VBE fixes (Matthew Mastracci)
+ - PIT fixes (aka Win98 hardware probe and "VGA slowness" bug)
+ - IDE master only fixes (aka Win98 CD-ROM probe bug)
+ - ARM load/store half word fix (Ulrich Hecht)
+ - FDC fixes for Win98
+
+version 0.5.4:
+
+ - qemu-fast fixes
+ - BIOS area protection fix (aka EMM386.EXE fix) (Mike Nordell)
+ - keyboard/mouse fix (Mike Nordell)
+ - IDE fixes (Linux did not recognized slave drivers)
+ - VM86 EIP masking fix (aka NT5 install fix) (Mike Nordell)
+ - QEMU can now boot a PowerPC Linux kernel (Jocelyn Mayer)
+ - User mode network stack
+ - imul imm8 fix + 0x82 opcode support (Hidemi KAWAI)
+ - precise self modifying code (aka BeOS install bug)
+
+version 0.5.3:
+
+ - added Bochs VESA VBE support
+ - VGA memory map mode 3 access fix (OS/2 install fix)
+ - IDE fixes (Jens Axboe)
+ - CPU interrupt fixes
+ - fixed various TLB invalidation cases (NT install)
+ - fixed cr0.WP semantics (XP install)
+ - direct chaining support for SPARC and PowerPC (faster)
+ - ARM NWFPE support (initial patch by Ulrich Hecht)
+ - added specific x86 to x86 translator (close to native performance
+ in qemu-i386 and qemu-fast)
+ - shm syscalls support (Paul McKerras)
+ - added accurate CR0.MP/ME/TS emulation
+ - fixed DMA memory write access (Win95 boot floppy fix)
+ - graphical x86 linux loader
+ - command line monitor
+ - generic removable device support
+ - support of CD-ROM change
+ - multiple network interface support
+ - initial x86-64 host support (Gwenole Beauchesne)
+ - lret to outer priviledge fix (OS/2 install fix)
+ - task switch fixes (SkyOS boot)
+ - VM save/restore commands
+ - new timer API
+ - more precise RTC emulation (periodic timers + time updates)
+ - Win32 port (initial patch by Kazu)
+
+version 0.5.2:
+
+ - improved soft MMU speed (assembly functions and specializing)
+ - improved multitasking speed by avoiding flushing TBs when
+ switching tasks
+ - improved qemu-fast speed
+ - improved self modifying code handling (big performance gain in
+ softmmu mode).
+ - fixed IO checking
+ - fixed CD-ROM detection (win98 install CD)
+ - fixed addseg real mode bug (GRUB boot fix)
+ - added ROM memory support (win98 boot)
+ - fixed 'call Ev' in case of paging exception
+ - updated the script 'qemu-binfmt-conf.sh' to use QEMU automagically
+ when launching executables for the supported target CPUs.
+ - PowerPC system emulation update (Jocelyn Mayer)
+ - PC floppy emulation and DMA fixes (Jocelyn Mayer)
+ - polled mode for PIC (Jocelyn Mayer)
+ - fixed PTE dirty bit handling
+ - fixed xadd same reg bug
+ - fixed cmpxchg exception safeness
+ - access to virtual memory in gdb stub
+ - task gate and NT flag fixes
+ - eflags optimisation fix for string operations
+
+version 0.5.1:
+
+ - float access fixes when using soft mmu
+ - PC emulation support on PowerPC
+ - A20 support
+ - IDE CD-ROM emulation
+ - ARM fixes (Ulrich Hecht)
+ - SB16 emulation (malc)
+ - IRET and INT fixes in VM86 mode with IOPL=3
+ - Port I/Os use TSS io map
+ - Full task switching/task gate support
+ - added verr, verw, arpl, fcmovxx
+ - PowerPC target support (Jocelyn Mayer)
+ - Major SPARC target fixes (dynamically linked programs begin to work)
+
+version 0.5.0:
+
+ - full hardware level VGA emulation
+ - graphical display with SDL
+ - added PS/2 mouse and keyboard emulation
+ - popw (%esp) fix
+ - mov to/from segment data width fix
+ - added real mode support
+ - added Bochs BIOS and LGPL'ed VGA BIOS loader in qemu
+ - m68k host port (Richard Zidlicky)
+ - partial soft MMU support for memory mapped I/Os
+ - multi-target build
+ - fixed: no error code in hardware interrupts
+ - fixed: pop ss, mov ss, x and sti disable hardware irqs for the next insn
+ - correct single stepping thru string operations
+ - preliminary SPARC target support (Thomas M. Ogrisegg)
+ - tun-fd option (Rusty Russell)
+ - automatic IDE geometry detection
+ - renamed 'vl' to qemu[-fast] and user qemu to qemu-{cpu}.
+ - added man page
+ - added full soft mmu mode to launch unpatched OSes.
+
+version 0.4.3:
+
+ - x86 exception fix in case of nop instruction.
+ - gcc 3.2.2 bug workaround (RedHat 9 fix)
+ - sparc and Alpha host fixes
+ - many ARM target fixes: 'ls' and 'bash' can be launched.
+
+version 0.4.2:
+
+ - many exception handling fixes (can compile a Linux kernel inside vl)
+ - IDE emulation support
+ - initial GDB stub support
+ - deferred update support for disk images (Rusty Russell)
+ - accept User Mode Linux Copy On Write disk images
+ - SMP kernels can at least be booted
+
+version 0.4.1:
+
+ - more accurate timer support in vl.
+ - more reliable NE2000 probe in vl.
+ - added 2.5.66 kernel in vl-test.
+ - added VLTMPDIR environment variable in vl.
+
+version 0.4:
+
+ - initial support for ring 0 x86 processor emulation
+ - fixed signal handling for correct dosemu DPMI emulation
+ - fast x86 MMU emulation with mmap()
+ - fixed popl (%esp) case
+ - Linux kernel can be executed by QEMU with the 'vl' command.
+
+version 0.3:
+
+ - initial support for ARM emulation
+ - added fnsave, frstor, fnstenv, fldenv FPU instructions
+ - added FPU register save in signal emulation
+ - initial ARM port
+ - Sparc and Alpha ports work on the regression test
+ - generic ioctl number conversion
+ - fixed ioctl type conversion
+
+version 0.2:
+
+ - PowerPC disassembly and ELF symbols output (Rusty Russell)
+ - flock support (Rusty Russell)
+ - ugetrlimit support (Rusty Russell)
+ - fstat64 fix (Rusty Russell)
+ - initial Alpha port (Falk Hueffner)
+ - initial IA64 port (Matt Wilson)
+ - initial Sparc and Sparc64 port (David S. Miller)
+ - added HLT instruction
+ - LRET instruction fix.
+ - added GPF generation for I/Os.
+ - added INT3 and TF flag support.
+ - SHL instruction C flag fix.
+ - mmap emulation for host page size > 4KB
+ - self-modifying code support
+ - better VM86 support (dosemu works on non trivial programs)
+ - precise exception support (EIP is computed correctly in most cases)
+ - more precise LDT/GDT/IDT emulation
+ - faster segment load in vm86 mode
+ - direct chaining of basic blocks (faster emulation)
+
+version 0.1.6:
+
+ - automatic library search system. QEMU can now work with unpatched
+ ELF dynamic loader and libc (Rusty Russell).
+ - ISO C warning fixes (Alistair Strachan)
+ - first self-virtualizable version (works only as long as the
+ translation cache is not flushed)
+ - RH9 fixes
+
+version 0.1.5:
+
+ - ppc64 support + personality() patch (Rusty Russell)
+ - first Alpha CPU patches (Falk Hueffner)
+ - removed bfd.h dependancy
+ - fixed shrd, shld, idivl and divl on PowerPC.
+ - fixed buggy glibc PowerPC rint() function (test-i386 passes now on PowerPC).
+
+version 0.1.4:
+
+ - more accurate VM86 emulation (can launch small DOS 16 bit
+ executables in wine).
+ - fixed push/pop fs/gs
+ - added iret instruction.
+ - added times() syscall and SIOCATMARK ioctl.
+
+version 0.1.3:
+
+ - S390 support (Ulrich Weigand)
+ - glibc 2.3.x compile fix (Ulrich Weigand)
+ - socketcall endian fix (Ulrich Weigand)
+ - struct sockaddr endian fix (Ulrich Weigand)
+ - sendmsg/recvmsg endian fix (Ulrich Weigand)
+ - execve endian fix (Ulrich Weigand)
+ - fdset endian fix (Ulrich Weigand)
+ - partial setsockopt syscall support (Ulrich Weigand)
+ - more accurate pushf/popf emulation
+ - first partial vm86() syscall support (can be used with runcom example).
+ - added bound, cmpxchg8b, cpuid instructions
+ - added 16 bit addressing support/override for string operations
+ - poll() fix
+
+version 0.1.2:
+
+ - compile fixes
+ - xlat instruction
+ - xchg instruction memory lock
+ - added simple vm86 example (not working with QEMU yet). The 54 byte
+ DOS executable 'pi_10.com' program was released by Bertram
+ Felgenhauer (more information at http://www.boo.net/~jasonp/pipage.html).
+
+version 0.1.1:
+
+ - glibc 2.2 compilation fixes
+ - added -s and -L options
+ - binary distribution of x86 glibc and wine
+ - big endian fixes in ELF loader and getdents.
+
+version 0.1:
+
+ - initial public release.
-# Order is important!
-SUBDIRS=gui memory iodev
+-include config-host.mak
-.PHONY: all clean install
+CFLAGS=-Wall -O2 -g -fno-strict-aliasing
+ifdef CONFIG_DARWIN
+CFLAGS+= -mdynamic-no-pic
+endif
+ifdef CONFIG_WIN32
+CFLAGS+=-fpack-struct
+endif
+LDFLAGS=-g
+LIBS=
+DEFINES+=-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
+TOOLS=qemu-img
+ifdef CONFIG_STATIC
+LDFLAGS+=-static
+endif
+DOCS=qemu-doc.html qemu-tech.html qemu.1
-all:
- @for subdir in $(SUBDIRS); do \
- $(MAKE) -C $$subdir $(MAKEDEFS) $@ || exit -1; \
- done
+all: $(DOCS) HEADERS
+ for d in $(TARGET_DIRS); do \
+ $(MAKE) -C $$d $@ || exit 1 ; \
+ done
+
+qemu-img: qemu-img.c block.c block-cow.c block-qcow.c aes.c block-vmdk.c block-cloop.c
+ $(CC) -DQEMU_TOOL $(CFLAGS) $(LDFLAGS) $(DEFINES) -o $@ $^ -lz $(LIBS)
+
+dyngen$(EXESUF): dyngen.c
+ $(HOST_CC) $(CFLAGS) $(DEFINES) -o $@ $^
clean:
- @for subdir in $(SUBDIRS); do \
- $(MAKE) -C $$subdir $(MAKEDEFS) $@ || exit -1; \
- done
-
-install:
- @for subdir in $(SUBDIRS); do \
- $(MAKE) -C $$subdir $(MAKEDEFS) $@ || exit -1; \
- done
+# avoid old build problems by removing potentially incorrect old files
+ rm -f config.mak config.h op-i386.h opc-i386.h gen-op-i386.h op-arm.h opc-arm.h gen-op-arm.h
+ rm -f *.o *.a $(TOOLS) dyngen$(EXESUF) TAGS qemu.pod *~ */*~
+ $(MAKE) -C tests clean
+ for d in $(TARGET_DIRS); do \
+ $(MAKE) -C $$d $@ || exit 1 ; \
+ done
+
+distclean: clean
+ rm -f config-host.mak config-host.h
+ rm -f keysym_adapter_sdl.h keysym_adapter_vnc.h
+ for d in $(TARGET_DIRS); do \
+ rm -rf $$d || exit 1 ; \
+ done
+
+KEYMAPS=da en-gb et fr fr-ch is lt modifiers no pt-br sv \
+ar de en-us fi fr-be hr it lv nl pl ru th \
+common de-ch es fo fr-ca hu ja mk nl-be pt sl tr
+
+install: all
+ mkdir -p "$(bindir)"
+ifndef CONFIG_WIN32
+# install -m 755 -s $(TOOLS) "$(bindir)"
+endif
+ mkdir -p "$(DESTDIR)/$(datadir)"
+ install -m 644 pc-bios/bios.bin pc-bios/vgabios.bin \
+ pc-bios/vgabios-cirrus.bin \
+ pc-bios/ppc_rom.bin \
+ pc-bios/proll.bin \
+ pc-bios/linux_boot.bin "$(DESTDIR)/$(datadir)"
+ mkdir -p "$(DESTDIR)/$(docdir)"
+ install -m 644 qemu-doc.html qemu-tech.html "$(DESTDIR)/$(docdir)"
+ifndef CONFIG_WIN32
+ mkdir -p "$(DESTDIR)/$(mandir)/man1"
+ install qemu.1 qemu-mkcow.1 "$(DESTDIR)/$(mandir)/man1"
+ mkdir -p "$(DESTDIR)/$(datadir)/keymaps"
+ install -m 644 $(addprefix keymaps/,$(KEYMAPS)) "$(DESTDIR)/$(datadir)/keymaps"
+endif
+ for d in $(TARGET_DIRS); do \
+ $(MAKE) -C $$d $@ || exit 1 ; \
+ done
+
+# various test targets
+test speed test2: all
+ $(MAKE) -C tests $@
+
+TAGS:
+ etags *.[ch] tests/*.[ch]
+
+# documentation
+%.html: %.texi
+ texi2html -monolithic -number $<
+
+qemu.1: qemu-doc.texi
+ ./texi2pod.pl $< qemu.pod
+ pod2man --section=1 --center=" " --release=" " qemu.pod > $@
+
+FILE=qemu-$(shell cat VERSION)
+
+# tar release (use 'make -k tar' on a checkouted tree)
+tar:
+ rm -rf /tmp/$(FILE)
+ cp -r . /tmp/$(FILE)
+ ( cd /tmp ; tar zcvf ~/$(FILE).tar.gz $(FILE) --exclude CVS )
+ rm -rf /tmp/$(FILE)
+
+# generate a binary distribution
+tarbin:
+ ( cd $(DESTDIR) ; tar zcvf ~/qemu-$(VERSION)-i386.tar.gz \
+ $(DESTDIR)/$(bindir)/qemu $(DESTDIR)/$(bindir)/qemu-fast \
+ $(DESTDIR)/$(bindir)/qemu-system-ppc \
+ $(DESTDIR)/$(bindir)/qemu-i386 \
+ $(DESTDIR)/$(bindir)/qemu-arm \
+ $(DESTDIR)/$(bindir)/qemu-sparc \
+ $(DESTDIR)/$(bindir)/qemu-ppc \
+ $(DESTDIR)/$(datadir)/bios.bin \
+ $(DESTDIR)/$(datadir)/vgabios.bin \
+ $(DESTDIR)/$(datadir)/vgabios-cirrus.bin \
+ $(DESTDIR)/$(datadir)/ppc_rom.bin \
+ $(DESTDIR)/$(datadir)/proll.bin \
+ $(DESTDIR)/$(datadir)/linux_boot.bin \
+ $(DESTDIR)/$(docdir)/qemu-doc.html \
+ $(DESTDIR)/$(docdir)/qemu-tech.html \
+ $(DESTDIR)/$(mandir)/man1/qemu.1 $(DESTDIR)/$(mandir)/man1/qemu-mkcow.1 )
+
+ifneq ($(wildcard .depend),)
+include .depend
+endif
+
+HEADERS:
+
+ifdef CONFIG_SDL
+HEADERS: keysym_adapter_sdl.h
+endif
+
+ifdef CONFIG_VNC
+HEADERS: keysym_adapter_vnc.h
+endif
+
+keysym_adapter_sdl.h: Makefile create_keysym_header.sh
+ sh create_keysym_header.sh sdl "$(SDL_CFLAGS)"
+
+keysym_adapter_vnc.h: Makefile create_keysym_header.sh
+ sh create_keysym_header.sh vnc "$(VNC_CFLAGS)"
+
+
--- /dev/null
+include config.mak
+
+#assume we directly put qemu code in tools/, same level as bochs dm(ioemu)
+XEN_PATH=../../..
+TARGET_PATH=$(SRC_PATH)/target-$(TARGET_ARCH)
+VPATH=$(SRC_PATH):$(TARGET_PATH):$(SRC_PATH)/hw:$(SRC_PATH)/audio
+DEFINES=-I. -I$(TARGET_PATH) -I$(SRC_PATH) -I$(XEN_PATH)/xen/include/public
+DEFINES+= -I$(XEN_PATH)/tools/libxc
+ifdef CONFIG_USER_ONLY
+VPATH+=:$(SRC_PATH)/linux-user
+DEFINES+=-I$(SRC_PATH)/linux-user -I$(SRC_PATH)/linux-user/$(TARGET_ARCH)
+endif
+CFLAGS=-Wall -O2 -g -fno-strict-aliasing
+LDFLAGS=-g
+LIBS=
+HELPER_CFLAGS=$(CFLAGS)
+DYNGEN=../dyngen$(EXESUF)
+# user emulator name
+QEMU_USER=qemu-$(TARGET_ARCH)
+# system emulator name
+ifdef CONFIG_SOFTMMU
+ifeq ($(TARGET_ARCH), i386)
+QEMU_SYSTEM=qemu$(EXESUF)
+else
+QEMU_SYSTEM=qemu-system-$(TARGET_ARCH)$(EXESUF)
+endif
+else
+QEMU_SYSTEM=qemu-fast
+endif
+
+QEMU_SYSTEM=qemu-dm
+PROGS=$(QEMU_SYSTEM)
+
+ifdef CONFIG_USER_ONLY
+PROGS=$(QEMU_USER)
+else
+ifeq ($(TARGET_ARCH), i386)
+
+ifeq ($(ARCH), i386)
+PROGS+=$(QEMU_SYSTEM)
+ifndef CONFIG_SOFTMMU
+CONFIG_STATIC=y
+endif
+else
+# the system emulator using soft mmu is portable
+ifdef CONFIG_SOFTMMU
+PROGS+=$(QEMU_SYSTEM)
+endif
+endif # ARCH != i386
+
+endif # TARGET_ARCH = i386
+
+ifeq ($(TARGET_ARCH), ppc)
+
+ifeq ($(ARCH), ppc)
+PROGS+=$(QEMU_SYSTEM)
+endif
+
+ifeq ($(ARCH), i386)
+ifdef CONFIG_SOFTMMU
+PROGS+=$(QEMU_SYSTEM)
+endif
+endif # ARCH = i386
+
+ifeq ($(ARCH), amd64)
+ifdef CONFIG_SOFTMMU
+PROGS+=$(QEMU_SYSTEM)
+endif
+endif # ARCH = amd64
+
+endif # TARGET_ARCH = ppc
+
+ifeq ($(TARGET_ARCH), sparc)
+
+ifeq ($(ARCH), ppc)
+PROGS+=$(QEMU_SYSTEM)
+endif
+
+ifeq ($(ARCH), i386)
+ifdef CONFIG_SOFTMMU
+PROGS+=$(QEMU_SYSTEM)
+endif
+endif # ARCH = i386
+
+ifeq ($(ARCH), amd64)
+ifdef CONFIG_SOFTMMU
+PROGS+=$(QEMU_SYSTEM)
+endif
+endif # ARCH = amd64
+
+endif # TARGET_ARCH = sparc
+endif # !CONFIG_USER_ONLY
+
+ifdef CONFIG_STATIC
+LDFLAGS+=-static
+endif
+
+ifeq ($(ARCH),i386)
+CFLAGS+=-fomit-frame-pointer
+OP_CFLAGS=$(CFLAGS) -mpreferred-stack-boundary=2
+ifeq ($(HAVE_GCC3_OPTIONS),yes)
+OP_CFLAGS+= -falign-functions=0 -fno-gcse
+else
+OP_CFLAGS+= -malign-functions=0
+endif
+
+ifdef TARGET_GPROF
+USE_I386_LD=y
+endif
+ifdef CONFIG_STATIC
+USE_I386_LD=y
+endif
+ifdef USE_I386_LD
+LDFLAGS+=-Wl,-T,$(SRC_PATH)/i386.ld
+else
+# WARNING: this LDFLAGS is _very_ tricky : qemu is an ELF shared object
+# that the kernel ELF loader considers as an executable. I think this
+# is the simplest way to make it self virtualizable!
+LDFLAGS+=-Wl,-shared
+endif
+endif
+
+ifeq ($(ARCH),amd64)
+OP_CFLAGS=$(CFLAGS) -falign-functions=0
+LDFLAGS+=-Wl,-T,$(SRC_PATH)/amd64.ld
+endif
+
+ifeq ($(ARCH),ppc)
+CFLAGS+= -D__powerpc__
+OP_CFLAGS=$(CFLAGS)
+LDFLAGS+=-Wl,-T,$(SRC_PATH)/ppc.ld
+endif
+
+ifeq ($(ARCH),s390)
+OP_CFLAGS=$(CFLAGS)
+LDFLAGS+=-Wl,-T,$(SRC_PATH)/s390.ld
+endif
+
+ifeq ($(ARCH),sparc)
+CFLAGS+=-m32 -ffixed-g1 -ffixed-g2 -ffixed-g3 -ffixed-g6
+LDFLAGS+=-m32
+OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -ffixed-i0
+HELPER_CFLAGS=$(CFLAGS) -ffixed-i0 -mflat
+# -static is used to avoid g1/g3 usage by the dynamic linker
+LDFLAGS+=-Wl,-T,$(SRC_PATH)/sparc.ld -static
+endif
+
+ifeq ($(ARCH),sparc64)
+CFLAGS+=-m64 -ffixed-g1 -ffixed-g2 -ffixed-g3 -ffixed-g6
+LDFLAGS+=-m64
+OP_CFLAGS=$(CFLAGS) -fno-delayed-branch -ffixed-i0
+endif
+
+ifeq ($(ARCH),alpha)
+# -msmall-data is not used because we want two-instruction relocations
+# for the constant constructions
+OP_CFLAGS=-Wall -O2 -g
+# Ensure there's only a single GP
+CFLAGS += -msmall-data
+LDFLAGS+=-Wl,-T,$(SRC_PATH)/alpha.ld
+endif
+
+ifeq ($(ARCH),ia64)
+OP_CFLAGS=$(CFLAGS)
+endif
+
+ifeq ($(ARCH),arm)
+OP_CFLAGS=$(CFLAGS) -mno-sched-prolog
+LDFLAGS+=-Wl,-T,$(SRC_PATH)/arm.ld
+endif
+
+ifeq ($(ARCH),m68k)
+OP_CFLAGS=$(CFLAGS) -fomit-frame-pointer
+LDFLAGS+=-Wl,-T,m68k.ld
+endif
+
+ifeq ($(HAVE_GCC3_OPTIONS),yes)
+# very important to generate a return at the end of every operation
+OP_CFLAGS+=-fno-reorder-blocks -fno-optimize-sibling-calls
+endif
+
+ifeq ($(CONFIG_DARWIN),yes)
+OP_CFLAGS+= -mdynamic-no-pic
+endif
+
+#########################################################
+
+DEFINES+=-D_GNU_SOURCE -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE
+LIBS+=-lm -L$(XEN_PATH)/dist/install/usr/$(LIBDIR) -lxc -lxutil
+ifndef CONFIG_USER_ONLY
+LIBS+=-lz
+endif
+ifdef CONFIG_WIN32
+LIBS+=-lwinmm -lws2_32 -liphlpapi
+endif
+
+# profiling code
+ifdef TARGET_GPROF
+LDFLAGS+=-p
+main.o: CFLAGS+=-p
+endif
+
+OBJS= elfload.o main.o syscall.o mmap.o signal.o path.o osdep.o thunk.o
+ifeq ($(TARGET_ARCH), i386)
+OBJS+= vm86.o
+endif
+ifeq ($(TARGET_ARCH), arm)
+OBJS+=nwfpe/softfloat.o nwfpe/fpa11.o nwfpe/fpa11_cpdo.o \
+nwfpe/fpa11_cpdt.o nwfpe/fpa11_cprt.o nwfpe/fpopcode.o nwfpe/single_cpdo.o \
+ nwfpe/double_cpdo.o nwfpe/extended_cpdo.o
+endif
+SRCS:= $(OBJS:.o=.c)
+OBJS+= libqemu.a
+
+# cpu emulator library
+LIBOBJS=
+
+ifeq ($(TARGET_ARCH), i386)
+LIBOBJS+= helper2.o
+ifeq ($(ARCH), i386)
+LIBOBJS+=translate-copy.o
+endif
+endif
+
+ifeq ($(TARGET_ARCH), ppc)
+LIBOBJS+= op_helper.o helper.o
+endif
+
+ifeq ($(TARGET_ARCH), sparc)
+LIBOBJS+= op_helper.o helper.o
+endif
+
+all: $(PROGS)
+
+$(QEMU_USER): $(OBJS)
+ $(CC) $(LDFLAGS) -o $@ $^ $(LIBS)
+ifeq ($(ARCH),alpha)
+# Mark as 32 bit binary, i. e. it will be mapped into the low 31 bit of
+# the address space (31 bit so sign extending doesn't matter)
+ echo -ne '\001\000\000\000' | dd of=qemu bs=1 seek=48 count=4 conv=notrunc
+endif
+
+# must use static linking to avoid leaving stuff in virtual address space
+VL_OBJS=vl.o exec.o monitor.o osdep.o block.o readline.o pci.o console.o
+#VL_OBJS+=block-cow.o block-qcow.o block-vmdk.o block-cloop.o
+VL_OBJS+= block-cloop.o
+
+SOUND_HW = sb16.o
+AUDIODRV = audio.o noaudio.o wavaudio.o
+ifdef CONFIG_SDL
+AUDIODRV += sdlaudio.o
+endif
+ifdef CONFIG_OSS
+AUDIODRV += ossaudio.o
+endif
+
+pc.o: DEFINES := -DUSE_SB16 $(DEFINES)
+
+ifdef CONFIG_ADLIB
+SOUND_HW += fmopl.o adlib.o
+endif
+
+ifdef CONFIG_FMOD
+AUDIODRV += fmodaudio.o
+audio.o fmodaudio.o: DEFINES := -I$(CONFIG_FMOD_INC) $(DEFINES)
+LIBS += $(CONFIG_FMOD_LIB)
+endif
+
+# Hardware support
+VL_OBJS+= ide.o ne2000.o pckbd.o vga.o dma.o
+VL_OBJS+= fdc.o mc146818rtc.o serial.o i8259.o i8254.o pc.o
+
+ifeq ($(TARGET_ARCH), ppc)
+VL_OBJS+= ppc.o ide.o ne2000.o pckbd.o vga.o $(SOUND_HW) dma.o $(AUDIODRV)
+VL_OBJS+= mc146818rtc.o serial.o i8259.o i8254.o fdc.o m48t59.o
+VL_OBJS+= ppc_prep.o ppc_chrp.o cuda.o adb.o openpic.o mixeng.o
+endif
+ifeq ($(TARGET_ARCH), sparc)
+VL_OBJS+= sun4m.o tcx.o lance.o iommu.o sched.o m48t08.o magic-load.o timer.o
+endif
+ifdef CONFIG_GDBSTUB
+VL_OBJS+=gdbstub.o
+endif
+ifdef CONFIG_VNC
+VL_OBJS+=vnc.o
+endif
+ifdef CONFIG_SDL
+VL_OBJS+=sdl.o
+endif
+ifdef CONFIG_SLIRP
+DEFINES+=-I$(SRC_PATH)/slirp
+SLIRP_OBJS=cksum.o if.o ip_icmp.o ip_input.o ip_output.o \
+slirp.o mbuf.o misc.o sbuf.o socket.o tcp_input.o tcp_output.o \
+tcp_subr.o tcp_timer.o udp.o bootp.o debug.o tftp.o
+VL_OBJS+=$(addprefix slirp/, $(SLIRP_OBJS))
+endif
+
+VL_LDFLAGS=
+# specific flags are needed for non soft mmu emulator
+ifdef CONFIG_STATIC
+VL_LDFLAGS+=-static
+endif
+ifndef CONFIG_SOFTMMU
+VL_LDFLAGS+=-Wl,-T,$(SRC_PATH)/i386-vl.ld
+endif
+ifndef CONFIG_DARWIN
+ifndef CONFIG_WIN32
+VL_LIBS=-lutil
+endif
+endif
+
+$(QEMU_SYSTEM): $(VL_OBJS) libqemu.a
+ $(CC) $(VL_LDFLAGS) -o $@ $^ $(LIBS) $(SDL_LIBS) $(VNC_LIBS) $(VL_LIBS)
+
+vnc.o: vnc.c keyboard_rdesktop.c
+ $(CC) $(CFLAGS) $(DEFINES) $(VNC_CFLAGS) -c -o $@ $<
+
+sdl.o: sdl.c keyboard_rdesktop.c
+ $(CC) $(CFLAGS) $(DEFINES) $(SDL_CFLAGS) -c -o $@ $<
+
+sdlaudio.o: sdlaudio.c
+ $(CC) $(CFLAGS) $(DEFINES) $(SDL_CFLAGS) -c -o $@ $<
+
+depend: $(SRCS)
+ $(CC) -MM $(CFLAGS) $(DEFINES) $^ 1>.depend
+
+# libqemu
+
+libqemu.a: $(LIBOBJS)
+ rm -f $@
+ $(AR) rcs $@ $(LIBOBJS)
+
+translate.o: translate.c gen-op.h opc.h cpu.h
+
+translate-all.o: translate-all.c op.h opc.h cpu.h
+
+op.h: op.o $(DYNGEN)
+ $(DYNGEN) -o $@ $<
+
+opc.h: op.o $(DYNGEN)
+ $(DYNGEN) -c -o $@ $<
+
+gen-op.h: op.o $(DYNGEN)
+ $(DYNGEN) -g -o $@ $<
+
+op.o: op.c
+ $(CC) $(OP_CFLAGS) $(DEFINES) -c -o $@ $<
+
+helper.o: helper.c
+ $(CC) $(HELPER_CFLAGS) $(DEFINES) -c -o $@ $<
+
+ifeq ($(TARGET_ARCH), i386)
+op.o: op.c opreg_template.h ops_template.h ops_template_mem.h ops_mem.h
+endif
+
+ifeq ($(TARGET_ARCH), arm)
+op.o: op.c op_template.h
+endif
+
+ifeq ($(TARGET_ARCH), sparc)
+op.o: op.c op_template.h op_mem.h
+endif
+
+ifeq ($(TARGET_ARCH), ppc)
+op.o: op.c op_template.h op_mem.h
+op_helper.o: op_helper_mem.h
+endif
+
+mixeng.o: mixeng.c mixeng.h mixeng_template.h
+
+%.o: %.c
+ $(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
+
+%.o: %.S
+ $(CC) $(DEFINES) -c -o $@ $<
+
+clean:
+ rm -rf *.o *.a *~ $(PROGS) gen-op.h opc.h op.h nwfpe slirp qemu-vgaram-bin
+
+install: all
+ if [ ! -d $(DESTDIR)$(bindir) ];then mkdir -p $(DESTDIR)$(bindir);fi
+ if [ ! -d $(DESTDIR)$(configdir) ];then mkdir -p $(DESTDIR)$(configdir);fi
+ifneq ($(PROGS),)
+ install -m 755 -s $(PROGS) "$(DESTDIR)$(bindir)"
+endif
+ install -m 755 device-model "$(DESTDIR)$(bindir)"
+ install -m 755 qemu-ifup "$(DESTDIR)$(configdir)"
+ gunzip -c qemu-vgaram-bin.gz >qemu-vgaram-bin
+ install -m 755 qemu-vgaram-bin "$(DESTDIR)$(configdir)"
+ifneq ($(wildcard .depend),)
+include .depend
+endif
--- /dev/null
+The QEMU x86 emulator
+---------------------
+
+INSTALLATION
+------------
+
+Type
+
+ ./configure
+ make
+
+to build qemu, qemu-CPU and libqemu.a (CPU is the name of the various
+supported target CPUs).
+
+Type
+
+ make install
+
+to install QEMU in /usr/local
+
+Tested tool versions
+--------------------
+
+In order to compile QEMU succesfully, it is very important that you
+have the right tools. The most important one is gcc. I cannot guaranty
+that QEMU works if you do not use a tested gcc version. Look at
+'configure' and 'Makefile' if you want to make a different gcc
+version work.
+
+host gcc binutils glibc linux distribution
+----------------------------------------------------------------------
+x86 2.95.2 2.13.2 2.1.3 2.4.18
+ 3.2 2.13.2 2.1.3 2.4.18
+ 2.96 2.11.93.0.2 2.2.5 2.4.18 Red Hat 7.3
+ 3.2.2 2.13.90.0.18 2.3.2 2.4.20 Red Hat 9
+
+PowerPC 3.3 [4] 2.13.90.0.18 2.3.1 2.4.20briq
+ 3.2
+
+Alpha 3.3 [1] 2.14.90.0.4 2.2.5 2.2.20 [2] Debian 3.0
+
+Sparc32 2.95.4 2.12.90.0.1 2.2.5 2.4.18 Debian 3.0
+
+ARM 2.95.4 2.12.90.0.1 2.2.5 2.4.9 [3] Debian 3.0
+
+[1] On Alpha, QEMU needs the gcc 'visibility' attribute only available
+ for gcc version >= 3.3.
+[2] Linux >= 2.4.20 is necessary for precise exception support
+ (untested).
+[3] 2.4.9-ac10-rmk2-np1-cerf2
+
+[4] gcc 2.95.x generates invalid code when using too many register
+variables. You must use gcc 3.x on PowerPC.
+
+Documentation
+-------------
+
+Read the documentation in qemu-doc.html.
+
+
+Fabrice Bellard.
\ No newline at end of file
--- /dev/null
+Information about the various packages used to build the current qemu
+x86 binary distribution:
+
+* gcc 2.95.2 was used for the build. A glibc 2.1.3 Debian distribution
+ was used to get most of the binary packages.
+
+* wine-20020411 tarball
+
+ ./configure --prefix=/usr/local/wine-i386
+
+ All exe and libs were stripped. Some compile time tools and the
+ includes were deleted.
+
+* ldconfig was launched to build the library links:
+
+ qemu-i386 /usr/gnemul/qemu-i386/bin/ldconfig-i386 -C /usr/gnemul/qemu-i386/etc/ld.so.cache
--- /dev/null
+short term:
+----------
+- debug option in 'configure' script + disable -fomit-frame-pointer
+- Solaris display error with Cirrus VGA
+ (http://lists.gnu.org/archive/html/qemu-devel/2004-10/msg00390.html).
+- Precise VGA timings for old games/demos (malc patch)
+- merge PIC spurious interrupt patch
+- merge VNC keyboard patch
+- merge Solaris patch
+- merge ARM patches + self modifying code patch (Paul Brook)
+- warning for OS/2: must not use 128 MB memory
+- config file (at least for windows/Mac OS X)
+- commit message if execution of code in IO memory
+- update doc: PCI infos.
+- VNC patch + Synaptic patch.
+- basic VGA optimizations
+- test sysenter/sysexit and fxsr for L4 pistachio 686
+- physical memory cache (reduce qemu-fast address space size to about 32 MB)
+- better code fetch (different exception handling + CS.limit support)
+- do not resize vga if invalid size.
+- avoid looping if only exceptions
+- cycle counter for all archs
+- TLB code protection support for PPC
+- see openMosix Doc
+- disable SMC handling for ARM/SPARC/PPC (not finished)
+- see undefined flags for BTx insn
+- user/kernel PUSHL/POPL in helper.c
+- keyboard output buffer filling timing emulation
+- return UD exception if LOCK prefix incorrectly used
+- test ldt limit < 7 ?
+- tests for each target CPU
+- fix CCOP optimisation
+- fix all remaining thread lock issues (must put TBs in a specific invalid
+ state, find a solution for tb_flush()).
+- fix arm fpu rounding (at least for float->integer conversions)
+- SMP support
+
+ppc specific:
+------------
+- TLB invalidate not needed if msr_pr changes
+- endianness bugs in do_load_fpscr and do_store_fpscr
+- SPR_ENCODE() not useful
+- enable shift optimizations ?
+
+lower priority:
+--------------
+- more friendly BIOS (logo)
+- int15 ah=86: use better timing
+- HDD geometry in CMOS (not used except for very old DOS programs)
+- suppress shift_mem ops
+- fix some 16 bit sp push/pop overflow (pusha/popa, lcall lret)
+- sysenter/sysexit emulation
+- optimize FPU operations (evaluate x87 stack pointer statically)
+- add IPC syscalls
+- use -msoft-float on ARM
+- use kernel traps for unaligned accesses on ARM ?
+- handle rare page fault cases (in particular if page fault in helpers or
+ in syscall emulation code).
+- fix thread stack freeing (use kernel 2.5.x CLONE_CHILD_CLEARTID)
+- more syscalls (in particular all 64 bit ones, IPCs, fix 64 bit
+ issues, fix 16 bit uid issues)
+- use page_unprotect_range in every suitable syscall to handle all
+ cases of self modifying code.
+- use gcc as a backend to generate better code (easy to do by using
+ op-i386.c operations as local inline functions).
+- add SSE2/MMX operations
--- /dev/null
+0.6.1
\ No newline at end of file
--- /dev/null
+/*
+ * QEMU System Emulator block driver
+ *
+ * Copyright (c) 2004 Johannes E. Schindelin
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+#include "block_int.h"
+#include <zlib.h>
+
+typedef struct BDRVCloopState {
+ int fd;
+ uint32_t block_size;
+ uint32_t n_blocks;
+ uint64_t* offsets;
+ uint32_t sectors_per_block;
+ uint32_t current_block;
+ char* compressed_block;
+ char* uncompressed_block;
+ z_stream zstream;
+} BDRVCloopState;
+
+static int cloop_probe(const uint8_t *buf, int buf_size, const char *filename)
+{
+ const char* magic_version_2_0="#!/bin/sh\n"
+ "#V2.0 Format\n"
+ "modprobe cloop file=$0 && mount -r -t iso9660 /dev/cloop $1\n";
+ int length=strlen(magic_version_2_0);
+ if(length>buf_size)
+ length=buf_size;
+ if(!memcmp(magic_version_2_0,buf,length))
+ return 2;
+ return 0;
+}
+
+static int cloop_open(BlockDriverState *bs, const char *filename)
+{
+ BDRVCloopState *s = bs->opaque;
+ uint32_t offsets_size,max_compressed_block_size=1,i;
+
+ s->fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
+ if (s->fd < 0)
+ return -1;
+ bs->read_only = 1;
+
+ /* read header */
+ if(lseek(s->fd,128,SEEK_SET)<0) {
+cloop_close:
+ close(s->fd);
+ return -1;
+ }
+ if(read(s->fd,&s->block_size,4)<4)
+ goto cloop_close;
+ s->block_size=be32_to_cpu(s->block_size);
+ if(read(s->fd,&s->n_blocks,4)<4)
+ goto cloop_close;
+ s->n_blocks=be32_to_cpu(s->n_blocks);
+
+ /* read offsets */
+ offsets_size=s->n_blocks*sizeof(uint64_t);
+ if(!(s->offsets=(uint64_t*)malloc(offsets_size)))
+ goto cloop_close;
+ if(read(s->fd,s->offsets,offsets_size)<offsets_size)
+ goto cloop_close;
+ for(i=0;i<s->n_blocks;i++) {
+ s->offsets[i]=be64_to_cpu(s->offsets[i]);
+ if(i>0) {
+ uint32_t size=s->offsets[i]-s->offsets[i-1];
+ if(size>max_compressed_block_size)
+ max_compressed_block_size=size;
+ }
+ }
+
+ /* initialize zlib engine */
+ if(!(s->compressed_block=(char*)malloc(max_compressed_block_size+1)))
+ goto cloop_close;
+ if(!(s->uncompressed_block=(char*)malloc(s->block_size)))
+ goto cloop_close;
+ if(inflateInit(&s->zstream) != Z_OK)
+ goto cloop_close;
+ s->current_block=s->n_blocks;
+
+ s->sectors_per_block = s->block_size/512;
+ bs->total_sectors = s->n_blocks*s->sectors_per_block;
+ return 0;
+}
+
+static inline int cloop_read_block(BDRVCloopState *s,int block_num)
+{
+ if(s->current_block != block_num) {
+ int ret;
+ uint32_t bytes = s->offsets[block_num+1]-s->offsets[block_num];
+
+ lseek(s->fd, s->offsets[block_num], SEEK_SET);
+ ret = read(s->fd, s->compressed_block, bytes);
+ if (ret != bytes)
+ return -1;
+
+ s->zstream.next_in = s->compressed_block;
+ s->zstream.avail_in = bytes;
+ s->zstream.next_out = s->uncompressed_block;
+ s->zstream.avail_out = s->block_size;
+ ret = inflateReset(&s->zstream);
+ if(ret != Z_OK)
+ return -1;
+ ret = inflate(&s->zstream, Z_FINISH);
+ if(ret != Z_STREAM_END || s->zstream.total_out != s->block_size)
+ return -1;
+
+ s->current_block = block_num;
+ }
+ return 0;
+}
+
+static int cloop_read(BlockDriverState *bs, int64_t sector_num,
+ uint8_t *buf, int nb_sectors)
+{
+ BDRVCloopState *s = bs->opaque;
+ int i;
+
+ for(i=0;i<nb_sectors;i++) {
+ uint32_t sector_offset_in_block=((sector_num+i)%s->sectors_per_block),
+ block_num=(sector_num+i)/s->sectors_per_block;
+ if(cloop_read_block(s, block_num) != 0)
+ return -1;
+ memcpy(buf+i*512,s->uncompressed_block+sector_offset_in_block*512,512);
+ }
+ return 0;
+}
+
+static void cloop_close(BlockDriverState *bs)
+{
+ BDRVCloopState *s = bs->opaque;
+ close(s->fd);
+ free(s->compressed_block);
+ free(s->uncompressed_block);
+ inflateEnd(&s->zstream);
+}
+
+BlockDriver bdrv_cloop = {
+ "cloop",
+ sizeof(BDRVCloopState),
+ cloop_probe,
+ cloop_open,
+ cloop_read,
+ NULL,
+ cloop_close,
+};
+
+
--- /dev/null
+/*
+ * Block driver for the COW format
+ *
+ * Copyright (c) 2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#ifndef _WIN32
+#include "vl.h"
+#include "block_int.h"
+#include <sys/mman.h>
+
+/**************************************************************/
+/* COW block driver using file system holes */
+
+/* user mode linux compatible COW file */
+#define COW_MAGIC 0x4f4f4f4d /* MOOO */
+#define COW_VERSION 2
+
+struct cow_header_v2 {
+ uint32_t magic;
+ uint32_t version;
+ char backing_file[1024];
+ int32_t mtime;
+ uint64_t size;
+ uint32_t sectorsize;
+};
+
+typedef struct BDRVCowState {
+ int fd;
+ uint8_t *cow_bitmap; /* if non NULL, COW mappings are used first */
+ uint8_t *cow_bitmap_addr; /* mmap address of cow_bitmap */
+ int cow_bitmap_size;
+ int64_t cow_sectors_offset;
+} BDRVCowState;
+
+static int cow_probe(const uint8_t *buf, int buf_size, const char *filename)
+{
+ const struct cow_header_v2 *cow_header = (const void *)buf;
+
+ if (be32_to_cpu(cow_header->magic) == COW_MAGIC &&
+ be32_to_cpu(cow_header->version) == COW_VERSION)
+ return 100;
+ else
+ return 0;
+}
+
+static int cow_open(BlockDriverState *bs, const char *filename)
+{
+ BDRVCowState *s = bs->opaque;
+ int fd;
+ struct cow_header_v2 cow_header;
+ int64_t size;
+
+ fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
+ if (fd < 0) {
+ fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
+ if (fd < 0)
+ return -1;
+ }
+ s->fd = fd;
+ /* see if it is a cow image */
+ if (read(fd, &cow_header, sizeof(cow_header)) != sizeof(cow_header)) {
+ goto fail;
+ }
+
+ if (be32_to_cpu(cow_header.magic) != COW_MAGIC ||
+ be32_to_cpu(cow_header.version) != COW_VERSION) {
+ goto fail;
+ }
+
+ /* cow image found */
+ size = be64_to_cpu(cow_header.size);
+ bs->total_sectors = size / 512;
+
+ pstrcpy(bs->backing_file, sizeof(bs->backing_file),
+ cow_header.backing_file);
+
+#if 0
+ if (cow_header.backing_file[0] != '\0') {
+ if (stat(cow_header.backing_file, &st) != 0) {
+ fprintf(stderr, "%s: could not find original disk image '%s'\n", filename, cow_header.backing_file);
+ goto fail;
+ }
+ if (st.st_mtime != be32_to_cpu(cow_header.mtime)) {
+ fprintf(stderr, "%s: original raw disk image '%s' does not match saved timestamp\n", filename, cow_header.backing_file);
+ goto fail;
+ }
+ fd = open(cow_header.backing_file, O_RDONLY | O_LARGEFILE);
+ if (fd < 0)
+ goto fail;
+ bs->fd = fd;
+ }
+#endif
+ /* mmap the bitmap */
+ s->cow_bitmap_size = ((bs->total_sectors + 7) >> 3) + sizeof(cow_header);
+ s->cow_bitmap_addr = mmap(get_mmap_addr(s->cow_bitmap_size),
+ s->cow_bitmap_size,
+ PROT_READ | PROT_WRITE,
+ MAP_SHARED, s->fd, 0);
+ if (s->cow_bitmap_addr == MAP_FAILED)
+ goto fail;
+ s->cow_bitmap = s->cow_bitmap_addr + sizeof(cow_header);
+ s->cow_sectors_offset = (s->cow_bitmap_size + 511) & ~511;
+ return 0;
+ fail:
+ close(fd);
+ return -1;
+}
+
+static inline void set_bit(uint8_t *bitmap, int64_t bitnum)
+{
+ bitmap[bitnum / 8] |= (1 << (bitnum%8));
+}
+
+static inline int is_bit_set(const uint8_t *bitmap, int64_t bitnum)
+{
+ return !!(bitmap[bitnum / 8] & (1 << (bitnum%8)));
+}
+
+
+/* Return true if first block has been changed (ie. current version is
+ * in COW file). Set the number of continuous blocks for which that
+ * is true. */
+static inline int is_changed(uint8_t *bitmap,
+ int64_t sector_num, int nb_sectors,
+ int *num_same)
+{
+ int changed;
+
+ if (!bitmap || nb_sectors == 0) {
+ *num_same = nb_sectors;
+ return 0;
+ }
+
+ changed = is_bit_set(bitmap, sector_num);
+ for (*num_same = 1; *num_same < nb_sectors; (*num_same)++) {
+ if (is_bit_set(bitmap, sector_num + *num_same) != changed)
+ break;
+ }
+
+ return changed;
+}
+
+static int cow_is_allocated(BlockDriverState *bs, int64_t sector_num,
+ int nb_sectors, int *pnum)
+{
+ BDRVCowState *s = bs->opaque;
+ return is_changed(s->cow_bitmap, sector_num, nb_sectors, pnum);
+}
+
+static int cow_read(BlockDriverState *bs, int64_t sector_num,
+ uint8_t *buf, int nb_sectors)
+{
+ BDRVCowState *s = bs->opaque;
+ int ret, n;
+
+ while (nb_sectors > 0) {
+ if (is_changed(s->cow_bitmap, sector_num, nb_sectors, &n)) {
+ lseek(s->fd, s->cow_sectors_offset + sector_num * 512, SEEK_SET);
+ ret = read(s->fd, buf, n * 512);
+ if (ret != n * 512)
+ return -1;
+ } else {
+ memset(buf, 0, n * 512);
+ }
+ nb_sectors -= n;
+ sector_num += n;
+ buf += n * 512;
+ }
+ return 0;
+}
+
+static int cow_write(BlockDriverState *bs, int64_t sector_num,
+ const uint8_t *buf, int nb_sectors)
+{
+ BDRVCowState *s = bs->opaque;
+ int ret, i;
+
+ lseek(s->fd, s->cow_sectors_offset + sector_num * 512, SEEK_SET);
+ ret = write(s->fd, buf, nb_sectors * 512);
+ if (ret != nb_sectors * 512)
+ return -1;
+ for (i = 0; i < nb_sectors; i++)
+ set_bit(s->cow_bitmap, sector_num + i);
+ return 0;
+}
+
+static void cow_close(BlockDriverState *bs)
+{
+ BDRVCowState *s = bs->opaque;
+ munmap(s->cow_bitmap_addr, s->cow_bitmap_size);
+ close(s->fd);
+}
+
+static int cow_create(const char *filename, int64_t image_sectors,
+ const char *image_filename, int flags)
+{
+ int fd, cow_fd;
+ struct cow_header_v2 cow_header;
+ struct stat st;
+
+ if (flags)
+ return -ENOTSUP;
+
+ cow_fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
+ 0644);
+ if (cow_fd < 0)
+ return -1;
+ memset(&cow_header, 0, sizeof(cow_header));
+ cow_header.magic = cpu_to_be32(COW_MAGIC);
+ cow_header.version = cpu_to_be32(COW_VERSION);
+ if (image_filename) {
+ fd = open(image_filename, O_RDONLY | O_BINARY);
+ if (fd < 0) {
+ close(cow_fd);
+ return -1;
+ }
+ if (fstat(fd, &st) != 0) {
+ close(fd);
+ return -1;
+ }
+ close(fd);
+ cow_header.mtime = cpu_to_be32(st.st_mtime);
+ realpath(image_filename, cow_header.backing_file);
+ }
+ cow_header.sectorsize = cpu_to_be32(512);
+ cow_header.size = cpu_to_be64(image_sectors * 512);
+ write(cow_fd, &cow_header, sizeof(cow_header));
+ /* resize to include at least all the bitmap */
+ ftruncate(cow_fd, sizeof(cow_header) + ((image_sectors + 7) >> 3));
+ close(cow_fd);
+ return 0;
+}
+
+BlockDriver bdrv_cow = {
+ "cow",
+ sizeof(BDRVCowState),
+ cow_probe,
+ cow_open,
+ cow_read,
+ cow_write,
+ cow_close,
+ cow_create,
+ cow_is_allocated,
+};
+#endif
--- /dev/null
+/*
+ * Block driver for the QCOW format
+ *
+ * Copyright (c) 2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+#include "block_int.h"
+#include <zlib.h>
+#include "aes.h"
+
+/**************************************************************/
+/* QEMU COW block driver with compression and encryption support */
+
+#define QCOW_MAGIC (('Q' << 24) | ('F' << 16) | ('I' << 8) | 0xfb)
+#define QCOW_VERSION 1
+
+#define QCOW_CRYPT_NONE 0
+#define QCOW_CRYPT_AES 1
+
+#define QCOW_OFLAG_COMPRESSED (1LL << 63)
+
+typedef struct QCowHeader {
+ uint32_t magic;
+ uint32_t version;
+ uint64_t backing_file_offset;
+ uint32_t backing_file_size;
+ uint32_t mtime;
+ uint64_t size; /* in bytes */
+ uint8_t cluster_bits;
+ uint8_t l2_bits;
+ uint32_t crypt_method;
+ uint64_t l1_table_offset;
+} QCowHeader;
+
+#define L2_CACHE_SIZE 16
+
+typedef struct BDRVQcowState {
+ int fd;
+ int cluster_bits;
+ int cluster_size;
+ int cluster_sectors;
+ int l2_bits;
+ int l2_size;
+ int l1_size;
+ uint64_t cluster_offset_mask;
+ uint64_t l1_table_offset;
+ uint64_t *l1_table;
+ uint64_t *l2_cache;
+ uint64_t l2_cache_offsets[L2_CACHE_SIZE];
+ uint32_t l2_cache_counts[L2_CACHE_SIZE];
+ uint8_t *cluster_cache;
+ uint8_t *cluster_data;
+ uint64_t cluster_cache_offset;
+ uint32_t crypt_method; /* current crypt method, 0 if no key yet */
+ uint32_t crypt_method_header;
+ AES_KEY aes_encrypt_key;
+ AES_KEY aes_decrypt_key;
+} BDRVQcowState;
+
+static int decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset);
+
+static int qcow_probe(const uint8_t *buf, int buf_size, const char *filename)
+{
+ const QCowHeader *cow_header = (const void *)buf;
+
+ if (be32_to_cpu(cow_header->magic) == QCOW_MAGIC &&
+ be32_to_cpu(cow_header->version) == QCOW_VERSION)
+ return 100;
+ else
+ return 0;
+}
+
+static int qcow_open(BlockDriverState *bs, const char *filename)
+{
+ BDRVQcowState *s = bs->opaque;
+ int fd, len, i, shift;
+ QCowHeader header;
+
+ fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
+ if (fd < 0) {
+ fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
+ if (fd < 0)
+ return -1;
+ }
+ s->fd = fd;
+ if (read(fd, &header, sizeof(header)) != sizeof(header))
+ goto fail;
+ be32_to_cpus(&header.magic);
+ be32_to_cpus(&header.version);
+ be64_to_cpus(&header.backing_file_offset);
+ be32_to_cpus(&header.backing_file_size);
+ be32_to_cpus(&header.mtime);
+ be64_to_cpus(&header.size);
+ be32_to_cpus(&header.crypt_method);
+ be64_to_cpus(&header.l1_table_offset);
+
+ if (header.magic != QCOW_MAGIC || header.version != QCOW_VERSION)
+ goto fail;
+ if (header.size <= 1 || header.cluster_bits < 9)
+ goto fail;
+ if (header.crypt_method > QCOW_CRYPT_AES)
+ goto fail;
+ s->crypt_method_header = header.crypt_method;
+ if (s->crypt_method_header)
+ bs->encrypted = 1;
+ s->cluster_bits = header.cluster_bits;
+ s->cluster_size = 1 << s->cluster_bits;
+ s->cluster_sectors = 1 << (s->cluster_bits - 9);
+ s->l2_bits = header.l2_bits;
+ s->l2_size = 1 << s->l2_bits;
+ bs->total_sectors = header.size / 512;
+ s->cluster_offset_mask = (1LL << (63 - s->cluster_bits)) - 1;
+
+ /* read the level 1 table */
+ shift = s->cluster_bits + s->l2_bits;
+ s->l1_size = (header.size + (1LL << shift) - 1) >> shift;
+
+ s->l1_table_offset = header.l1_table_offset;
+ s->l1_table = qemu_malloc(s->l1_size * sizeof(uint64_t));
+ if (!s->l1_table)
+ goto fail;
+ lseek(fd, s->l1_table_offset, SEEK_SET);
+ if (read(fd, s->l1_table, s->l1_size * sizeof(uint64_t)) !=
+ s->l1_size * sizeof(uint64_t))
+ goto fail;
+ for(i = 0;i < s->l1_size; i++) {
+ be64_to_cpus(&s->l1_table[i]);
+ }
+ /* alloc L2 cache */
+ s->l2_cache = qemu_malloc(s->l2_size * L2_CACHE_SIZE * sizeof(uint64_t));
+ if (!s->l2_cache)
+ goto fail;
+ s->cluster_cache = qemu_malloc(s->cluster_size);
+ if (!s->cluster_cache)
+ goto fail;
+ s->cluster_data = qemu_malloc(s->cluster_size);
+ if (!s->cluster_data)
+ goto fail;
+ s->cluster_cache_offset = -1;
+
+ /* read the backing file name */
+ if (header.backing_file_offset != 0) {
+ len = header.backing_file_size;
+ if (len > 1023)
+ len = 1023;
+ lseek(fd, header.backing_file_offset, SEEK_SET);
+ if (read(fd, bs->backing_file, len) != len)
+ goto fail;
+ bs->backing_file[len] = '\0';
+ }
+ return 0;
+
+ fail:
+ qemu_free(s->l1_table);
+ qemu_free(s->l2_cache);
+ qemu_free(s->cluster_cache);
+ qemu_free(s->cluster_data);
+ close(fd);
+ return -1;
+}
+
+static int qcow_set_key(BlockDriverState *bs, const char *key)
+{
+ BDRVQcowState *s = bs->opaque;
+ uint8_t keybuf[16];
+ int len, i;
+
+ memset(keybuf, 0, 16);
+ len = strlen(key);
+ if (len > 16)
+ len = 16;
+ /* XXX: we could compress the chars to 7 bits to increase
+ entropy */
+ for(i = 0;i < len;i++) {
+ keybuf[i] = key[i];
+ }
+ s->crypt_method = s->crypt_method_header;
+
+ if (AES_set_encrypt_key(keybuf, 128, &s->aes_encrypt_key) != 0)
+ return -1;
+ if (AES_set_decrypt_key(keybuf, 128, &s->aes_decrypt_key) != 0)
+ return -1;
+#if 0
+ /* test */
+ {
+ uint8_t in[16];
+ uint8_t out[16];
+ uint8_t tmp[16];
+ for(i=0;i<16;i++)
+ in[i] = i;
+ AES_encrypt(in, tmp, &s->aes_encrypt_key);
+ AES_decrypt(tmp, out, &s->aes_decrypt_key);
+ for(i = 0; i < 16; i++)
+ printf(" %02x", tmp[i]);
+ printf("\n");
+ for(i = 0; i < 16; i++)
+ printf(" %02x", out[i]);
+ printf("\n");
+ }
+#endif
+ return 0;
+}
+
+/* The crypt function is compatible with the linux cryptoloop
+ algorithm for < 4 GB images. NOTE: out_buf == in_buf is
+ supported */
+static void encrypt_sectors(BDRVQcowState *s, int64_t sector_num,
+ uint8_t *out_buf, const uint8_t *in_buf,
+ int nb_sectors, int enc,
+ const AES_KEY *key)
+{
+ union {
+ uint64_t ll[2];
+ uint8_t b[16];
+ } ivec;
+ int i;
+
+ for(i = 0; i < nb_sectors; i++) {
+ ivec.ll[0] = cpu_to_le64(sector_num);
+ ivec.ll[1] = 0;
+ AES_cbc_encrypt(in_buf, out_buf, 512, key,
+ ivec.b, enc);
+ sector_num++;
+ in_buf += 512;
+ out_buf += 512;
+ }
+}
+
+/* 'allocate' is:
+ *
+ * 0 to not allocate.
+ *
+ * 1 to allocate a normal cluster (for sector indexes 'n_start' to
+ * 'n_end')
+ *
+ * 2 to allocate a compressed cluster of size
+ * 'compressed_size'. 'compressed_size' must be > 0 and <
+ * cluster_size
+ *
+ * return 0 if not allocated.
+ */
+static uint64_t get_cluster_offset(BlockDriverState *bs,
+ uint64_t offset, int allocate,
+ int compressed_size,
+ int n_start, int n_end)
+{
+ BDRVQcowState *s = bs->opaque;
+ int min_index, i, j, l1_index, l2_index;
+ uint64_t l2_offset, *l2_table, cluster_offset, tmp;
+ uint32_t min_count;
+ int new_l2_table;
+
+ l1_index = offset >> (s->l2_bits + s->cluster_bits);
+ l2_offset = s->l1_table[l1_index];
+ new_l2_table = 0;
+ if (!l2_offset) {
+ if (!allocate)
+ return 0;
+ /* allocate a new l2 entry */
+ l2_offset = lseek(s->fd, 0, SEEK_END);
+ /* round to cluster size */
+ l2_offset = (l2_offset + s->cluster_size - 1) & ~(s->cluster_size - 1);
+ /* update the L1 entry */
+ s->l1_table[l1_index] = l2_offset;
+ tmp = cpu_to_be64(l2_offset);
+ lseek(s->fd, s->l1_table_offset + l1_index * sizeof(tmp), SEEK_SET);
+ if (write(s->fd, &tmp, sizeof(tmp)) != sizeof(tmp))
+ return 0;
+ new_l2_table = 1;
+ }
+ for(i = 0; i < L2_CACHE_SIZE; i++) {
+ if (l2_offset == s->l2_cache_offsets[i]) {
+ /* increment the hit count */
+ if (++s->l2_cache_counts[i] == 0xffffffff) {
+ for(j = 0; j < L2_CACHE_SIZE; j++) {
+ s->l2_cache_counts[j] >>= 1;
+ }
+ }
+ l2_table = s->l2_cache + (i << s->l2_bits);
+ goto found;
+ }
+ }
+ /* not found: load a new entry in the least used one */
+ min_index = 0;
+ min_count = 0xffffffff;
+ for(i = 0; i < L2_CACHE_SIZE; i++) {
+ if (s->l2_cache_counts[i] < min_count) {
+ min_count = s->l2_cache_counts[i];
+ min_index = i;
+ }
+ }
+ l2_table = s->l2_cache + (min_index << s->l2_bits);
+ lseek(s->fd, l2_offset, SEEK_SET);
+ if (new_l2_table) {
+ memset(l2_table, 0, s->l2_size * sizeof(uint64_t));
+ if (write(s->fd, l2_table, s->l2_size * sizeof(uint64_t)) !=
+ s->l2_size * sizeof(uint64_t))
+ return 0;
+ } else {
+ if (read(s->fd, l2_table, s->l2_size * sizeof(uint64_t)) !=
+ s->l2_size * sizeof(uint64_t))
+ return 0;
+ }
+ s->l2_cache_offsets[min_index] = l2_offset;
+ s->l2_cache_counts[min_index] = 1;
+ found:
+ l2_index = (offset >> s->cluster_bits) & (s->l2_size - 1);
+ cluster_offset = be64_to_cpu(l2_table[l2_index]);
+ if (!cluster_offset ||
+ ((cluster_offset & QCOW_OFLAG_COMPRESSED) && allocate == 1)) {
+ if (!allocate)
+ return 0;
+ /* allocate a new cluster */
+ if ((cluster_offset & QCOW_OFLAG_COMPRESSED) &&
+ (n_end - n_start) < s->cluster_sectors) {
+ /* if the cluster is already compressed, we must
+ decompress it in the case it is not completely
+ overwritten */
+ if (decompress_cluster(s, cluster_offset) < 0)
+ return 0;
+ cluster_offset = lseek(s->fd, 0, SEEK_END);
+ cluster_offset = (cluster_offset + s->cluster_size - 1) &
+ ~(s->cluster_size - 1);
+ /* write the cluster content */
+ lseek(s->fd, cluster_offset, SEEK_SET);
+ if (write(s->fd, s->cluster_cache, s->cluster_size) !=
+ s->cluster_size)
+ return -1;
+ } else {
+ cluster_offset = lseek(s->fd, 0, SEEK_END);
+ if (allocate == 1) {
+ /* round to cluster size */
+ cluster_offset = (cluster_offset + s->cluster_size - 1) &
+ ~(s->cluster_size - 1);
+ ftruncate(s->fd, cluster_offset + s->cluster_size);
+ /* if encrypted, we must initialize the cluster
+ content which won't be written */
+ if (s->crypt_method &&
+ (n_end - n_start) < s->cluster_sectors) {
+ uint64_t start_sect;
+ start_sect = (offset & ~(s->cluster_size - 1)) >> 9;
+ memset(s->cluster_data + 512, 0xaa, 512);
+ for(i = 0; i < s->cluster_sectors; i++) {
+ if (i < n_start || i >= n_end) {
+ encrypt_sectors(s, start_sect + i,
+ s->cluster_data,
+ s->cluster_data + 512, 1, 1,
+ &s->aes_encrypt_key);
+ lseek(s->fd, cluster_offset + i * 512, SEEK_SET);
+ if (write(s->fd, s->cluster_data, 512) != 512)
+ return -1;
+ }
+ }
+ }
+ } else {
+ cluster_offset |= QCOW_OFLAG_COMPRESSED |
+ (uint64_t)compressed_size << (63 - s->cluster_bits);
+ }
+ }
+ /* update L2 table */
+ tmp = cpu_to_be64(cluster_offset);
+ l2_table[l2_index] = tmp;
+ lseek(s->fd, l2_offset + l2_index * sizeof(tmp), SEEK_SET);
+ if (write(s->fd, &tmp, sizeof(tmp)) != sizeof(tmp))
+ return 0;
+ }
+ return cluster_offset;
+}
+
+static int qcow_is_allocated(BlockDriverState *bs, int64_t sector_num,
+ int nb_sectors, int *pnum)
+{
+ BDRVQcowState *s = bs->opaque;
+ int index_in_cluster, n;
+ uint64_t cluster_offset;
+
+ cluster_offset = get_cluster_offset(bs, sector_num << 9, 0, 0, 0, 0);
+ index_in_cluster = sector_num & (s->cluster_sectors - 1);
+ n = s->cluster_sectors - index_in_cluster;
+ if (n > nb_sectors)
+ n = nb_sectors;
+ *pnum = n;
+ return (cluster_offset != 0);
+}
+
+static int decompress_buffer(uint8_t *out_buf, int out_buf_size,
+ const uint8_t *buf, int buf_size)
+{
+ z_stream strm1, *strm = &strm1;
+ int ret, out_len;
+
+ memset(strm, 0, sizeof(*strm));
+
+ strm->next_in = (uint8_t *)buf;
+ strm->avail_in = buf_size;
+ strm->next_out = out_buf;
+ strm->avail_out = out_buf_size;
+
+ ret = inflateInit2(strm, -12);
+ if (ret != Z_OK)
+ return -1;
+ ret = inflate(strm, Z_FINISH);
+ out_len = strm->next_out - out_buf;
+ if ((ret != Z_STREAM_END && ret != Z_BUF_ERROR) ||
+ out_len != out_buf_size) {
+ inflateEnd(strm);
+ return -1;
+ }
+ inflateEnd(strm);
+ return 0;
+}
+
+static int decompress_cluster(BDRVQcowState *s, uint64_t cluster_offset)
+{
+ int ret, csize;
+ uint64_t coffset;
+
+ coffset = cluster_offset & s->cluster_offset_mask;
+ if (s->cluster_cache_offset != coffset) {
+ csize = cluster_offset >> (63 - s->cluster_bits);
+ csize &= (s->cluster_size - 1);
+ lseek(s->fd, coffset, SEEK_SET);
+ ret = read(s->fd, s->cluster_data, csize);
+ if (ret != csize)
+ return -1;
+ if (decompress_buffer(s->cluster_cache, s->cluster_size,
+ s->cluster_data, csize) < 0) {
+ return -1;
+ }
+ s->cluster_cache_offset = coffset;
+ }
+ return 0;
+}
+
+static int qcow_read(BlockDriverState *bs, int64_t sector_num,
+ uint8_t *buf, int nb_sectors)
+{
+ BDRVQcowState *s = bs->opaque;
+ int ret, index_in_cluster, n;
+ uint64_t cluster_offset;
+
+ while (nb_sectors > 0) {
+ cluster_offset = get_cluster_offset(bs, sector_num << 9, 0, 0, 0, 0);
+ index_in_cluster = sector_num & (s->cluster_sectors - 1);
+ n = s->cluster_sectors - index_in_cluster;
+ if (n > nb_sectors)
+ n = nb_sectors;
+ if (!cluster_offset) {
+ memset(buf, 0, 512 * n);
+ } else if (cluster_offset & QCOW_OFLAG_COMPRESSED) {
+ if (decompress_cluster(s, cluster_offset) < 0)
+ return -1;
+ memcpy(buf, s->cluster_cache + index_in_cluster * 512, 512 * n);
+ } else {
+ lseek(s->fd, cluster_offset + index_in_cluster * 512, SEEK_SET);
+ ret = read(s->fd, buf, n * 512);
+ if (ret != n * 512)
+ return -1;
+ if (s->crypt_method) {
+ encrypt_sectors(s, sector_num, buf, buf, n, 0,
+ &s->aes_decrypt_key);
+ }
+ }
+ nb_sectors -= n;
+ sector_num += n;
+ buf += n * 512;
+ }
+ return 0;
+}
+
+static int qcow_write(BlockDriverState *bs, int64_t sector_num,
+ const uint8_t *buf, int nb_sectors)
+{
+ BDRVQcowState *s = bs->opaque;
+ int ret, index_in_cluster, n;
+ uint64_t cluster_offset;
+
+ while (nb_sectors > 0) {
+ index_in_cluster = sector_num & (s->cluster_sectors - 1);
+ n = s->cluster_sectors - index_in_cluster;
+ if (n > nb_sectors)
+ n = nb_sectors;
+ cluster_offset = get_cluster_offset(bs, sector_num << 9, 1, 0,
+ index_in_cluster,
+ index_in_cluster + n);
+ if (!cluster_offset)
+ return -1;
+ lseek(s->fd, cluster_offset + index_in_cluster * 512, SEEK_SET);
+ if (s->crypt_method) {
+ encrypt_sectors(s, sector_num, s->cluster_data, buf, n, 1,
+ &s->aes_encrypt_key);
+ ret = write(s->fd, s->cluster_data, n * 512);
+ } else {
+ ret = write(s->fd, buf, n * 512);
+ }
+ if (ret != n * 512)
+ return -1;
+ nb_sectors -= n;
+ sector_num += n;
+ buf += n * 512;
+ }
+ s->cluster_cache_offset = -1; /* disable compressed cache */
+ return 0;
+}
+
+static void qcow_close(BlockDriverState *bs)
+{
+ BDRVQcowState *s = bs->opaque;
+ qemu_free(s->l1_table);
+ qemu_free(s->l2_cache);
+ qemu_free(s->cluster_cache);
+ qemu_free(s->cluster_data);
+ close(s->fd);
+}
+
+static int qcow_create(const char *filename, int64_t total_size,
+ const char *backing_file, int flags)
+{
+ int fd, header_size, backing_filename_len, l1_size, i, shift;
+ QCowHeader header;
+ char backing_filename[1024];
+ uint64_t tmp;
+ struct stat st;
+
+ fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
+ 0644);
+ if (fd < 0)
+ return -1;
+ memset(&header, 0, sizeof(header));
+ header.magic = cpu_to_be32(QCOW_MAGIC);
+ header.version = cpu_to_be32(QCOW_VERSION);
+ header.size = cpu_to_be64(total_size * 512);
+ header_size = sizeof(header);
+ backing_filename_len = 0;
+ if (backing_file) {
+ realpath(backing_file, backing_filename);
+ if (stat(backing_filename, &st) != 0) {
+ return -1;
+ }
+ header.mtime = cpu_to_be32(st.st_mtime);
+ header.backing_file_offset = cpu_to_be64(header_size);
+ backing_filename_len = strlen(backing_filename);
+ header.backing_file_size = cpu_to_be32(backing_filename_len);
+ header_size += backing_filename_len;
+ header.cluster_bits = 9; /* 512 byte cluster to avoid copying
+ unmodifyed sectors */
+ header.l2_bits = 12; /* 32 KB L2 tables */
+ } else {
+ header.cluster_bits = 12; /* 4 KB clusters */
+ header.l2_bits = 9; /* 4 KB L2 tables */
+ }
+ header_size = (header_size + 7) & ~7;
+ shift = header.cluster_bits + header.l2_bits;
+ l1_size = ((total_size * 512) + (1LL << shift) - 1) >> shift;
+
+ header.l1_table_offset = cpu_to_be64(header_size);
+ if (flags) {
+ header.crypt_method = cpu_to_be32(QCOW_CRYPT_AES);
+ } else {
+ header.crypt_method = cpu_to_be32(QCOW_CRYPT_NONE);
+ }
+
+ /* write all the data */
+ write(fd, &header, sizeof(header));
+ if (backing_file) {
+ write(fd, backing_filename, backing_filename_len);
+ }
+ lseek(fd, header_size, SEEK_SET);
+ tmp = 0;
+ for(i = 0;i < l1_size; i++) {
+ write(fd, &tmp, sizeof(tmp));
+ }
+ close(fd);
+ return 0;
+}
+
+int qcow_get_cluster_size(BlockDriverState *bs)
+{
+ BDRVQcowState *s = bs->opaque;
+ if (bs->drv != &bdrv_qcow)
+ return -1;
+ return s->cluster_size;
+}
+
+/* XXX: put compressed sectors first, then all the cluster aligned
+ tables to avoid losing bytes in alignment */
+int qcow_compress_cluster(BlockDriverState *bs, int64_t sector_num,
+ const uint8_t *buf)
+{
+ BDRVQcowState *s = bs->opaque;
+ z_stream strm;
+ int ret, out_len;
+ uint8_t *out_buf;
+ uint64_t cluster_offset;
+
+ if (bs->drv != &bdrv_qcow)
+ return -1;
+
+ out_buf = qemu_malloc(s->cluster_size + (s->cluster_size / 1000) + 128);
+ if (!out_buf)
+ return -1;
+
+ /* best compression, small window, no zlib header */
+ memset(&strm, 0, sizeof(strm));
+ ret = deflateInit2(&strm, Z_DEFAULT_COMPRESSION,
+ Z_DEFLATED, -12,
+ 9, Z_DEFAULT_STRATEGY);
+ if (ret != 0) {
+ qemu_free(out_buf);
+ return -1;
+ }
+
+ strm.avail_in = s->cluster_size;
+ strm.next_in = (uint8_t *)buf;
+ strm.avail_out = s->cluster_size;
+ strm.next_out = out_buf;
+
+ ret = deflate(&strm, Z_FINISH);
+ if (ret != Z_STREAM_END && ret != Z_OK) {
+ qemu_free(out_buf);
+ deflateEnd(&strm);
+ return -1;
+ }
+ out_len = strm.next_out - out_buf;
+
+ deflateEnd(&strm);
+
+ if (ret != Z_STREAM_END || out_len >= s->cluster_size) {
+ /* could not compress: write normal cluster */
+ qcow_write(bs, sector_num, buf, s->cluster_sectors);
+ } else {
+ cluster_offset = get_cluster_offset(bs, sector_num << 9, 2,
+ out_len, 0, 0);
+ cluster_offset &= s->cluster_offset_mask;
+ lseek(s->fd, cluster_offset, SEEK_SET);
+ if (write(s->fd, out_buf, out_len) != out_len) {
+ qemu_free(out_buf);
+ return -1;
+ }
+ }
+
+ qemu_free(out_buf);
+ return 0;
+}
+
+BlockDriver bdrv_qcow = {
+ "qcow",
+ sizeof(BDRVQcowState),
+ qcow_probe,
+ qcow_open,
+ qcow_read,
+ qcow_write,
+ qcow_close,
+ qcow_create,
+ qcow_is_allocated,
+ qcow_set_key,
+};
+
+
--- /dev/null
+/*
+ * Block driver for the VMDK format
+ *
+ * Copyright (c) 2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+#include "block_int.h"
+
+/* XXX: this code is untested */
+/* XXX: add write support */
+
+#define VMDK3_MAGIC (('C' << 24) | ('O' << 16) | ('W' << 8) | 'D')
+#define VMDK4_MAGIC (('K' << 24) | ('D' << 16) | ('M' << 8) | 'V')
+
+typedef struct {
+ uint32_t version;
+ uint32_t flags;
+ uint32_t disk_sectors;
+ uint32_t granularity;
+ uint32_t l1dir_offset;
+ uint32_t l1dir_size;
+ uint32_t file_sectors;
+ uint32_t cylinders;
+ uint32_t heads;
+ uint32_t sectors_per_track;
+} VMDK3Header;
+
+typedef struct {
+ uint32_t version;
+ uint32_t flags;
+ int64_t capacity;
+ int64_t granularity;
+ int64_t desc_offset;
+ int64_t desc_size;
+ int32_t num_gtes_per_gte;
+ int64_t rgd_offset;
+ int64_t gd_offset;
+ int64_t grain_offset;
+ char filler[1];
+ char check_bytes[4];
+} VMDK4Header;
+
+#define L2_CACHE_SIZE 16
+
+typedef struct BDRVVmdkState {
+ int fd;
+ int64_t l1_table_offset;
+ uint32_t *l1_table;
+ unsigned int l1_size;
+ uint32_t l1_entry_sectors;
+
+ unsigned int l2_size;
+ uint32_t *l2_cache;
+ uint32_t l2_cache_offsets[L2_CACHE_SIZE];
+ uint32_t l2_cache_counts[L2_CACHE_SIZE];
+
+ unsigned int cluster_sectors;
+} BDRVVmdkState;
+
+static int vmdk_probe(const uint8_t *buf, int buf_size, const char *filename)
+{
+ uint32_t magic;
+
+ if (buf_size < 4)
+ return 0;
+ magic = be32_to_cpu(*(uint32_t *)buf);
+ if (magic == VMDK3_MAGIC ||
+ magic == VMDK4_MAGIC)
+ return 100;
+ else
+ return 0;
+}
+
+static int vmdk_open(BlockDriverState *bs, const char *filename)
+{
+ BDRVVmdkState *s = bs->opaque;
+ int fd, i;
+ uint32_t magic;
+ int l1_size;
+
+ fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
+ if (fd < 0)
+ return -1;
+ if (read(fd, &magic, sizeof(magic)) != sizeof(magic))
+ goto fail;
+ magic = be32_to_cpu(magic);
+ if (magic == VMDK3_MAGIC) {
+ VMDK3Header header;
+ if (read(fd, &header, sizeof(header)) !=
+ sizeof(header))
+ goto fail;
+ s->cluster_sectors = le32_to_cpu(header.granularity);
+ s->l2_size = 1 << 9;
+ s->l1_size = 1 << 6;
+ bs->total_sectors = le32_to_cpu(header.disk_sectors);
+ s->l1_table_offset = le32_to_cpu(header.l1dir_offset) * 512;
+ s->l1_entry_sectors = s->l2_size * s->cluster_sectors;
+ } else if (magic == VMDK4_MAGIC) {
+ VMDK4Header header;
+
+ if (read(fd, &header, sizeof(header)) != sizeof(header))
+ goto fail;
+ bs->total_sectors = le32_to_cpu(header.capacity);
+ s->cluster_sectors = le32_to_cpu(header.granularity);
+ s->l2_size = le32_to_cpu(header.num_gtes_per_gte);
+ s->l1_entry_sectors = s->l2_size * s->cluster_sectors;
+ if (s->l1_entry_sectors <= 0)
+ goto fail;
+ s->l1_size = (bs->total_sectors + s->l1_entry_sectors - 1)
+ / s->l1_entry_sectors;
+ s->l1_table_offset = le64_to_cpu(header.rgd_offset) * 512;
+ } else {
+ goto fail;
+ }
+ /* read the L1 table */
+ l1_size = s->l1_size * sizeof(uint32_t);
+ s->l1_table = qemu_malloc(l1_size);
+ if (!s->l1_table)
+ goto fail;
+ if (lseek(fd, s->l1_table_offset, SEEK_SET) == -1)
+ goto fail;
+ if (read(fd, s->l1_table, l1_size) != l1_size)
+ goto fail;
+ for(i = 0; i < s->l1_size; i++) {
+ le32_to_cpus(&s->l1_table[i]);
+ }
+
+ s->l2_cache = qemu_malloc(s->l2_size * L2_CACHE_SIZE * sizeof(uint32_t));
+ if (!s->l2_cache)
+ goto fail;
+ s->fd = fd;
+ /* XXX: currently only read only */
+ bs->read_only = 1;
+ return 0;
+ fail:
+ qemu_free(s->l1_table);
+ qemu_free(s->l2_cache);
+ close(fd);
+ return -1;
+}
+
+static uint64_t get_cluster_offset(BlockDriverState *bs,
+ uint64_t offset)
+{
+ BDRVVmdkState *s = bs->opaque;
+ unsigned int l1_index, l2_offset, l2_index;
+ int min_index, i, j;
+ uint32_t min_count, *l2_table;
+ uint64_t cluster_offset;
+
+ l1_index = (offset >> 9) / s->l1_entry_sectors;
+ if (l1_index >= s->l1_size)
+ return 0;
+ l2_offset = s->l1_table[l1_index];
+ if (!l2_offset)
+ return 0;
+
+ for(i = 0; i < L2_CACHE_SIZE; i++) {
+ if (l2_offset == s->l2_cache_offsets[i]) {
+ /* increment the hit count */
+ if (++s->l2_cache_counts[i] == 0xffffffff) {
+ for(j = 0; j < L2_CACHE_SIZE; j++) {
+ s->l2_cache_counts[j] >>= 1;
+ }
+ }
+ l2_table = s->l2_cache + (i * s->l2_size);
+ goto found;
+ }
+ }
+ /* not found: load a new entry in the least used one */
+ min_index = 0;
+ min_count = 0xffffffff;
+ for(i = 0; i < L2_CACHE_SIZE; i++) {
+ if (s->l2_cache_counts[i] < min_count) {
+ min_count = s->l2_cache_counts[i];
+ min_index = i;
+ }
+ }
+ l2_table = s->l2_cache + (min_index * s->l2_size);
+ lseek(s->fd, (int64_t)l2_offset * 512, SEEK_SET);
+ if (read(s->fd, l2_table, s->l2_size * sizeof(uint32_t)) !=
+ s->l2_size * sizeof(uint32_t))
+ return 0;
+ s->l2_cache_offsets[min_index] = l2_offset;
+ s->l2_cache_counts[min_index] = 1;
+ found:
+ l2_index = ((offset >> 9) / s->cluster_sectors) % s->l2_size;
+ cluster_offset = le32_to_cpu(l2_table[l2_index]);
+ cluster_offset <<= 9;
+ return cluster_offset;
+}
+
+static int vmdk_is_allocated(BlockDriverState *bs, int64_t sector_num,
+ int nb_sectors, int *pnum)
+{
+ BDRVVmdkState *s = bs->opaque;
+ int index_in_cluster, n;
+ uint64_t cluster_offset;
+
+ cluster_offset = get_cluster_offset(bs, sector_num << 9);
+ index_in_cluster = sector_num % s->cluster_sectors;
+ n = s->cluster_sectors - index_in_cluster;
+ if (n > nb_sectors)
+ n = nb_sectors;
+ *pnum = n;
+ return (cluster_offset != 0);
+}
+
+static int vmdk_read(BlockDriverState *bs, int64_t sector_num,
+ uint8_t *buf, int nb_sectors)
+{
+ BDRVVmdkState *s = bs->opaque;
+ int ret, index_in_cluster, n;
+ uint64_t cluster_offset;
+
+ while (nb_sectors > 0) {
+ cluster_offset = get_cluster_offset(bs, sector_num << 9);
+ index_in_cluster = sector_num % s->cluster_sectors;
+ n = s->cluster_sectors - index_in_cluster;
+ if (n > nb_sectors)
+ n = nb_sectors;
+ if (!cluster_offset) {
+ memset(buf, 0, 512 * n);
+ } else {
+ lseek(s->fd, cluster_offset + index_in_cluster * 512, SEEK_SET);
+ ret = read(s->fd, buf, n * 512);
+ if (ret != n * 512)
+ return -1;
+ }
+ nb_sectors -= n;
+ sector_num += n;
+ buf += n * 512;
+ }
+ return 0;
+}
+
+static int vmdk_write(BlockDriverState *bs, int64_t sector_num,
+ const uint8_t *buf, int nb_sectors)
+{
+ return -1;
+}
+
+static void vmdk_close(BlockDriverState *bs)
+{
+ BDRVVmdkState *s = bs->opaque;
+ qemu_free(s->l1_table);
+ qemu_free(s->l2_cache);
+ close(s->fd);
+}
+
+BlockDriver bdrv_vmdk = {
+ "vmdk",
+ sizeof(BDRVVmdkState),
+ vmdk_probe,
+ vmdk_open,
+ vmdk_read,
+ vmdk_write,
+ vmdk_close,
+ NULL, /* no create yet */
+ vmdk_is_allocated,
+};
--- /dev/null
+/*
+ * QEMU System Emulator block driver
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+#include "block_int.h"
+
+static BlockDriverState *bdrv_first;
+static BlockDriver *first_drv;
+
+void bdrv_register(BlockDriver *bdrv)
+{
+ bdrv->next = first_drv;
+ first_drv = bdrv;
+}
+
+/* create a new block device (by default it is empty) */
+BlockDriverState *bdrv_new(const char *device_name)
+{
+ BlockDriverState **pbs, *bs;
+
+ bs = qemu_mallocz(sizeof(BlockDriverState));
+ if(!bs)
+ return NULL;
+ pstrcpy(bs->device_name, sizeof(bs->device_name), device_name);
+ if (device_name[0] != '\0') {
+ /* insert at the end */
+ pbs = &bdrv_first;
+ while (*pbs != NULL)
+ pbs = &(*pbs)->next;
+ *pbs = bs;
+ }
+ return bs;
+}
+
+BlockDriver *bdrv_find_format(const char *format_name)
+{
+ BlockDriver *drv1;
+ for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
+ if (!strcmp(drv1->format_name, format_name))
+ return drv1;
+ }
+ return NULL;
+}
+
+int bdrv_create(BlockDriver *drv,
+ const char *filename, int64_t size_in_sectors,
+ const char *backing_file, int flags)
+{
+ if (!drv->bdrv_create)
+ return -ENOTSUP;
+ return drv->bdrv_create(filename, size_in_sectors, backing_file, flags);
+}
+
+static BlockDriver *find_image_format(const char *filename)
+{
+ int fd, ret, score, score_max;
+ BlockDriver *drv1, *drv;
+ uint8_t buf[1024];
+
+ fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
+ if (fd < 0)
+ return NULL;
+ ret = read(fd, buf, sizeof(buf));
+ if (ret < 0) {
+ close(fd);
+ return NULL;
+ }
+ close(fd);
+
+ drv = NULL;
+ score_max = 0;
+ for(drv1 = first_drv; drv1 != NULL; drv1 = drv1->next) {
+ score = drv1->bdrv_probe(buf, ret, filename);
+ if (score > score_max) {
+ score_max = score;
+ drv = drv1;
+ }
+ }
+ return drv;
+}
+
+int bdrv_open(BlockDriverState *bs, const char *filename, int snapshot)
+{
+ return bdrv_open2(bs, filename, snapshot, NULL);
+}
+
+int bdrv_open2(BlockDriverState *bs, const char *filename, int snapshot,
+ BlockDriver *drv)
+{
+ int ret;
+
+ bs->read_only = 0;
+ bs->is_temporary = 0;
+ bs->encrypted = 0;
+
+ pstrcpy(bs->filename, sizeof(bs->filename), filename);
+ if (!drv) {
+ drv = find_image_format(filename);
+ if (!drv)
+ return -1;
+ }
+ bs->drv = drv;
+ bs->opaque = qemu_mallocz(drv->instance_size);
+ if (bs->opaque == NULL && drv->instance_size > 0)
+ return -1;
+
+ ret = drv->bdrv_open(bs, filename);
+ if (ret < 0) {
+ qemu_free(bs->opaque);
+ return -1;
+ }
+#ifndef _WIN32
+ if (bs->is_temporary) {
+ unlink(filename);
+ }
+#endif
+ if (bs->backing_file[0] != '\0' && drv->bdrv_is_allocated) {
+ /* if there is a backing file, use it */
+ bs->backing_hd = bdrv_new("");
+ if (!bs->backing_hd) {
+ fail:
+ bdrv_close(bs);
+ return -1;
+ }
+ if (bdrv_open(bs->backing_hd, bs->backing_file, 0) < 0)
+ goto fail;
+ }
+
+ bs->inserted = 1;
+
+ /* call the change callback */
+ if (bs->change_cb)
+ bs->change_cb(bs->change_opaque);
+
+ return 0;
+}
+
+void bdrv_close(BlockDriverState *bs)
+{
+ if (bs->inserted) {
+ if (bs->backing_hd)
+ bdrv_delete(bs->backing_hd);
+ bs->drv->bdrv_close(bs);
+ qemu_free(bs->opaque);
+#ifdef _WIN32
+ if (bs->is_temporary) {
+ unlink(bs->filename);
+ }
+#endif
+ bs->opaque = NULL;
+ bs->drv = NULL;
+ bs->inserted = 0;
+
+ /* call the change callback */
+ if (bs->change_cb)
+ bs->change_cb(bs->change_opaque);
+ }
+}
+
+void bdrv_delete(BlockDriverState *bs)
+{
+ /* XXX: remove the driver list */
+ bdrv_close(bs);
+ qemu_free(bs);
+}
+
+/* commit COW file into the raw image */
+int bdrv_commit(BlockDriverState *bs)
+{
+ int64_t i;
+ int n, j;
+ unsigned char sector[512];
+
+ if (!bs->inserted)
+ return -ENOENT;
+
+ if (bs->read_only) {
+ return -EACCES;
+ }
+
+ if (!bs->backing_hd) {
+ return -ENOTSUP;
+ }
+
+ for (i = 0; i < bs->total_sectors;) {
+ if (bs->drv->bdrv_is_allocated(bs, i, 65536, &n)) {
+ for(j = 0; j < n; j++) {
+ if (bdrv_read(bs, i, sector, 1) != 0) {
+ return -EIO;
+ }
+
+ if (bdrv_write(bs->backing_hd, i, sector, 1) != 0) {
+ return -EIO;
+ }
+ i++;
+ }
+ } else {
+ i += n;
+ }
+ }
+ return 0;
+}
+
+/* return -1 if error */
+int bdrv_read(BlockDriverState *bs, int64_t sector_num,
+ uint8_t *buf, int nb_sectors)
+{
+ int ret, n;
+ BlockDriver *drv = bs->drv;
+
+ if (!bs->inserted)
+ return -1;
+
+ while (nb_sectors > 0) {
+ if (sector_num == 0 && bs->boot_sector_enabled) {
+ memcpy(buf, bs->boot_sector_data, 512);
+ n = 1;
+ } else if (bs->backing_hd) {
+ if (drv->bdrv_is_allocated(bs, sector_num, nb_sectors, &n)) {
+ ret = drv->bdrv_read(bs, sector_num, buf, n);
+ if (ret < 0)
+ return -1;
+ } else {
+ /* read from the base image */
+ ret = bdrv_read(bs->backing_hd, sector_num, buf, n);
+ if (ret < 0)
+ return -1;
+ }
+ } else {
+ ret = drv->bdrv_read(bs, sector_num, buf, nb_sectors);
+ if (ret < 0)
+ return -1;
+ /* no need to loop */
+ break;
+ }
+ nb_sectors -= n;
+ sector_num += n;
+ buf += n * 512;
+ }
+ return 0;
+}
+
+/* return -1 if error */
+int bdrv_write(BlockDriverState *bs, int64_t sector_num,
+ const uint8_t *buf, int nb_sectors)
+{
+ if (!bs->inserted)
+ return -1;
+ if (bs->read_only)
+ return -1;
+ return bs->drv->bdrv_write(bs, sector_num, buf, nb_sectors);
+}
+
+void bdrv_get_geometry(BlockDriverState *bs, int64_t *nb_sectors_ptr)
+{
+ *nb_sectors_ptr = bs->total_sectors;
+}
+
+/* force a given boot sector. */
+void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size)
+{
+ bs->boot_sector_enabled = 1;
+ if (size > 512)
+ size = 512;
+ memcpy(bs->boot_sector_data, data, size);
+ memset(bs->boot_sector_data + size, 0, 512 - size);
+}
+
+void bdrv_set_geometry_hint(BlockDriverState *bs,
+ int cyls, int heads, int secs)
+{
+ bs->cyls = cyls;
+ bs->heads = heads;
+ bs->secs = secs;
+}
+
+void bdrv_set_type_hint(BlockDriverState *bs, int type)
+{
+ bs->type = type;
+ bs->removable = ((type == BDRV_TYPE_CDROM ||
+ type == BDRV_TYPE_FLOPPY));
+}
+
+void bdrv_get_geometry_hint(BlockDriverState *bs,
+ int *pcyls, int *pheads, int *psecs)
+{
+ *pcyls = bs->cyls;
+ *pheads = bs->heads;
+ *psecs = bs->secs;
+}
+
+int bdrv_get_type_hint(BlockDriverState *bs)
+{
+ return bs->type;
+}
+
+int bdrv_is_removable(BlockDriverState *bs)
+{
+ return bs->removable;
+}
+
+int bdrv_is_read_only(BlockDriverState *bs)
+{
+ return bs->read_only;
+}
+
+int bdrv_is_inserted(BlockDriverState *bs)
+{
+ return bs->inserted;
+}
+
+int bdrv_is_locked(BlockDriverState *bs)
+{
+ return bs->locked;
+}
+
+void bdrv_set_locked(BlockDriverState *bs, int locked)
+{
+ bs->locked = locked;
+}
+
+void bdrv_set_change_cb(BlockDriverState *bs,
+ void (*change_cb)(void *opaque), void *opaque)
+{
+ bs->change_cb = change_cb;
+ bs->change_opaque = opaque;
+}
+
+int bdrv_is_encrypted(BlockDriverState *bs)
+{
+ if (bs->backing_hd && bs->backing_hd->encrypted)
+ return 1;
+ return bs->encrypted;
+}
+
+int bdrv_set_key(BlockDriverState *bs, const char *key)
+{
+ int ret;
+ if (bs->backing_hd && bs->backing_hd->encrypted) {
+ ret = bdrv_set_key(bs->backing_hd, key);
+ if (ret < 0)
+ return ret;
+ if (!bs->encrypted)
+ return 0;
+ }
+ if (!bs->encrypted || !bs->drv || !bs->drv->bdrv_set_key)
+ return -1;
+ return bs->drv->bdrv_set_key(bs, key);
+}
+
+void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size)
+{
+ if (!bs->inserted || !bs->drv) {
+ buf[0] = '\0';
+ } else {
+ pstrcpy(buf, buf_size, bs->drv->format_name);
+ }
+}
+
+void bdrv_iterate_format(void (*it)(void *opaque, const char *name),
+ void *opaque)
+{
+ BlockDriver *drv;
+
+ for (drv = first_drv; drv != NULL; drv = drv->next) {
+ it(opaque, drv->format_name);
+ }
+}
+
+BlockDriverState *bdrv_find(const char *name)
+{
+ BlockDriverState *bs;
+
+ for (bs = bdrv_first; bs != NULL; bs = bs->next) {
+ if (!strcmp(name, bs->device_name))
+ return bs;
+ }
+ return NULL;
+}
+
+void bdrv_iterate(void (*it)(void *opaque, const char *name), void *opaque)
+{
+ BlockDriverState *bs;
+
+ for (bs = bdrv_first; bs != NULL; bs = bs->next) {
+ it(opaque, bs->device_name);
+ }
+}
+
+const char *bdrv_get_device_name(BlockDriverState *bs)
+{
+ return bs->device_name;
+}
+
+void bdrv_info(void)
+{
+ BlockDriverState *bs;
+
+ for (bs = bdrv_first; bs != NULL; bs = bs->next) {
+ term_printf("%s:", bs->device_name);
+ term_printf(" type=");
+ switch(bs->type) {
+ case BDRV_TYPE_HD:
+ term_printf("hd");
+ break;
+ case BDRV_TYPE_CDROM:
+ term_printf("cdrom");
+ break;
+ case BDRV_TYPE_FLOPPY:
+ term_printf("floppy");
+ break;
+ }
+ term_printf(" removable=%d", bs->removable);
+ if (bs->removable) {
+ term_printf(" locked=%d", bs->locked);
+ }
+ if (bs->inserted) {
+ term_printf(" file=%s", bs->filename);
+ if (bs->backing_file[0] != '\0')
+ term_printf(" backing_file=%s", bs->backing_file);
+ term_printf(" ro=%d", bs->read_only);
+ term_printf(" drv=%s", bs->drv->format_name);
+ if (bs->encrypted)
+ term_printf(" encrypted");
+ } else {
+ term_printf(" [not inserted]");
+ }
+ term_printf("\n");
+ }
+}
+
+
+/**************************************************************/
+/* RAW block driver */
+
+typedef struct BDRVRawState {
+ int fd;
+} BDRVRawState;
+
+static int raw_probe(const uint8_t *buf, int buf_size, const char *filename)
+{
+ return 1; /* maybe */
+}
+
+static int raw_open(BlockDriverState *bs, const char *filename)
+{
+ BDRVRawState *s = bs->opaque;
+ int fd;
+ int64_t size;
+
+ fd = open(filename, O_RDWR | O_BINARY | O_LARGEFILE);
+ if (fd < 0) {
+ fd = open(filename, O_RDONLY | O_BINARY | O_LARGEFILE);
+ if (fd < 0)
+ return -1;
+ bs->read_only = 1;
+ }
+ size = lseek(fd, 0, SEEK_END);
+ bs->total_sectors = size / 512;
+ s->fd = fd;
+ return 0;
+}
+
+static int raw_read(BlockDriverState *bs, int64_t sector_num,
+ uint8_t *buf, int nb_sectors)
+{
+ BDRVRawState *s = bs->opaque;
+ int ret;
+
+ lseek(s->fd, sector_num * 512, SEEK_SET);
+ ret = read(s->fd, buf, nb_sectors * 512);
+ if (ret != nb_sectors * 512)
+ return -1;
+ return 0;
+}
+
+static int raw_write(BlockDriverState *bs, int64_t sector_num,
+ const uint8_t *buf, int nb_sectors)
+{
+ BDRVRawState *s = bs->opaque;
+ int ret;
+
+ lseek(s->fd, sector_num * 512, SEEK_SET);
+ ret = write(s->fd, buf, nb_sectors * 512);
+ if (ret != nb_sectors * 512)
+ return -1;
+ return 0;
+}
+
+static void raw_close(BlockDriverState *bs)
+{
+ BDRVRawState *s = bs->opaque;
+ close(s->fd);
+}
+
+static int raw_create(const char *filename, int64_t total_size,
+ const char *backing_file, int flags)
+{
+ int fd;
+
+ if (flags || backing_file)
+ return -ENOTSUP;
+
+ fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY | O_LARGEFILE,
+ 0644);
+ if (fd < 0)
+ return -EIO;
+ ftruncate(fd, total_size * 512);
+ close(fd);
+ return 0;
+}
+
+BlockDriver bdrv_raw = {
+ "raw",
+ sizeof(BDRVRawState),
+ raw_probe,
+ raw_open,
+ raw_read,
+ raw_write,
+ raw_close,
+ raw_create,
+};
+
+void bdrv_init(void)
+{
+ bdrv_register(&bdrv_raw);
+ bdrv_register(&bdrv_cloop);
+}
--- /dev/null
+/*
+ * QEMU System Emulator block driver
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#ifndef BLOCK_INT_H
+#define BLOCK_INT_H
+
+struct BlockDriver {
+ const char *format_name;
+ int instance_size;
+ int (*bdrv_probe)(const uint8_t *buf, int buf_size, const char *filename);
+ int (*bdrv_open)(BlockDriverState *bs, const char *filename);
+ int (*bdrv_read)(BlockDriverState *bs, int64_t sector_num,
+ uint8_t *buf, int nb_sectors);
+ int (*bdrv_write)(BlockDriverState *bs, int64_t sector_num,
+ const uint8_t *buf, int nb_sectors);
+ void (*bdrv_close)(BlockDriverState *bs);
+ int (*bdrv_create)(const char *filename, int64_t total_sectors,
+ const char *backing_file, int flags);
+ int (*bdrv_is_allocated)(BlockDriverState *bs, int64_t sector_num,
+ int nb_sectors, int *pnum);
+ int (*bdrv_set_key)(BlockDriverState *bs, const char *key);
+ struct BlockDriver *next;
+};
+
+struct BlockDriverState {
+ int64_t total_sectors;
+ int read_only; /* if true, the media is read only */
+ int inserted; /* if true, the media is present */
+ int removable; /* if true, the media can be removed */
+ int locked; /* if true, the media cannot temporarily be ejected */
+ int encrypted; /* if true, the media is encrypted */
+ /* event callback when inserting/removing */
+ void (*change_cb)(void *opaque);
+ void *change_opaque;
+
+ BlockDriver *drv;
+ void *opaque;
+
+ int boot_sector_enabled;
+ uint8_t boot_sector_data[512];
+
+ char filename[1024];
+ char backing_file[1024]; /* if non zero, the image is a diff of
+ this file image */
+ int is_temporary;
+
+ BlockDriverState *backing_hd;
+
+ /* NOTE: the following infos are only hints for real hardware
+ drivers. They are not used by the block driver */
+ int cyls, heads, secs;
+ int type;
+ char device_name[32];
+ BlockDriverState *next;
+};
+
+#endif /* BLOCK_INT_H */
--- /dev/null
+#ifndef BSWAP_H
+#define BSWAP_H
+
+#include "config-host.h"
+
+#include <inttypes.h>
+
+#ifdef HAVE_BYTESWAP_H
+#include <byteswap.h>
+#else
+
+#define bswap_16(x) \
+({ \
+ uint16_t __x = (x); \
+ ((uint16_t)( \
+ (((uint16_t)(__x) & (uint16_t)0x00ffU) << 8) | \
+ (((uint16_t)(__x) & (uint16_t)0xff00U) >> 8) )); \
+})
+
+#define bswap_32(x) \
+({ \
+ uint32_t __x = (x); \
+ ((uint32_t)( \
+ (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
+ (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \
+ (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \
+ (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )); \
+})
+
+#define bswap_64(x) \
+({ \
+ uint64_t __x = (x); \
+ ((uint64_t)( \
+ (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000000000ffULL) << 56) | \
+ (uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000000000ff00ULL) << 40) | \
+ (uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \
+ (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000ff000000ULL) << 8) | \
+ (uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000ff00000000ULL) >> 8) | \
+ (uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \
+ (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \
+ (uint64_t)(((uint64_t)(__x) & (uint64_t)0xff00000000000000ULL) >> 56) )); \
+})
+
+#endif /* !HAVE_BYTESWAP_H */
+
+static inline uint16_t bswap16(uint16_t x)
+{
+ return bswap_16(x);
+}
+
+static inline uint32_t bswap32(uint32_t x)
+{
+ return bswap_32(x);
+}
+
+static inline uint64_t bswap64(uint64_t x)
+{
+ return bswap_64(x);
+}
+
+static inline void bswap16s(uint16_t *s)
+{
+ *s = bswap16(*s);
+}
+
+static inline void bswap32s(uint32_t *s)
+{
+ *s = bswap32(*s);
+}
+
+static inline void bswap64s(uint64_t *s)
+{
+ *s = bswap64(*s);
+}
+
+#if defined(WORDS_BIGENDIAN)
+#define be_bswap(v, size) (v)
+#define le_bswap(v, size) bswap ## size(v)
+#define be_bswaps(v, size)
+#define le_bswaps(p, size) *p = bswap ## size(*p);
+#else
+#define le_bswap(v, size) (v)
+#define be_bswap(v, size) bswap ## size(v)
+#define le_bswaps(v, size)
+#define be_bswaps(p, size) *p = bswap ## size(*p);
+#endif
+
+#define CPU_CONVERT(endian, size, type)\
+static inline type endian ## size ## _to_cpu(type v)\
+{\
+ return endian ## _bswap(v, size);\
+}\
+\
+static inline type cpu_to_ ## endian ## size(type v)\
+{\
+ return endian ## _bswap(v, size);\
+}\
+\
+static inline void endian ## size ## _to_cpus(type *p)\
+{\
+ endian ## _bswaps(p, size)\
+}\
+\
+static inline void cpu_to_ ## endian ## size ## s(type *p)\
+{\
+ endian ## _bswaps(p, size)\
+}\
+\
+static inline type endian ## size ## _to_cpup(const type *p)\
+{\
+ return endian ## size ## _to_cpu(*p);\
+}\
+\
+static inline void cpu_to_ ## endian ## size ## w(type *p, type v)\
+{\
+ *p = cpu_to_ ## endian ## size(v);\
+}
+
+CPU_CONVERT(be, 16, uint16_t)
+CPU_CONVERT(be, 32, uint32_t)
+CPU_CONVERT(be, 64, uint64_t)
+
+CPU_CONVERT(le, 16, uint16_t)
+CPU_CONVERT(le, 32, uint32_t)
+CPU_CONVERT(le, 64, uint64_t)
+
+/* unaligned versions (optimized for frequent unaligned accesses)*/
+
+#if defined(__i386__) || defined(__powerpc__)
+
+#define cpu_to_le16wu(p, v) cpu_to_le16w(p, v)
+#define cpu_to_le32wu(p, v) cpu_to_le32w(p, v)
+#define le16_to_cpupu(p) le16_to_cpup(p)
+#define le32_to_cpupu(p) le32_to_cpup(p)
+
+#define cpu_to_be16wu(p, v) cpu_to_be16w(p, v)
+#define cpu_to_be32wu(p, v) cpu_to_be32w(p, v)
+
+#else
+
+static inline void cpu_to_le16wu(uint16_t *p, uint16_t v)
+{
+ uint8_t *p1 = (uint8_t *)p;
+
+ p1[0] = v;
+ p1[1] = v >> 8;
+}
+
+static inline void cpu_to_le32wu(uint32_t *p, uint32_t v)
+{
+ uint8_t *p1 = (uint8_t *)p;
+
+ p1[0] = v;
+ p1[1] = v >> 8;
+ p1[2] = v >> 16;
+ p1[3] = v >> 24;
+}
+
+static inline uint16_t le16_to_cpupu(const uint16_t *p)
+{
+ const uint8_t *p1 = (const uint8_t *)p;
+ return p1[0] | (p1[1] << 8);
+}
+
+static inline uint32_t le32_to_cpupu(const uint32_t *p)
+{
+ const uint8_t *p1 = (const uint8_t *)p;
+ return p1[0] | (p1[1] << 8) | (p1[2] << 16) | (p1[3] << 24);
+}
+
+static inline void cpu_to_be16wu(uint16_t *p, uint16_t v)
+{
+ uint8_t *p1 = (uint8_t *)p;
+
+ p1[0] = v >> 8;
+ p1[1] = v;
+}
+
+static inline void cpu_to_be32wu(uint32_t *p, uint32_t v)
+{
+ uint8_t *p1 = (uint8_t *)p;
+
+ p1[0] = v >> 24;
+ p1[1] = v >> 16;
+ p1[2] = v >> 8;
+ p1[3] = v;
+}
+
+#endif
+
+#ifdef WORDS_BIGENDIAN
+#define cpu_to_32wu cpu_to_be32wu
+#else
+#define cpu_to_32wu cpu_to_le32wu
+#endif
+
+#undef le_bswap
+#undef be_bswap
+#undef le_bswaps
+#undef be_bswaps
+
+#endif /* BSWAP_H */
--- /dev/null
+#!/bin/sh
+#
+# qemu configure script (c) 2003 Fabrice Bellard
+#
+# set temporary file name
+if test ! -z "$TMPDIR" ; then
+ TMPDIR1="${TMPDIR}"
+elif test ! -z "$TEMPDIR" ; then
+ TMPDIR1="${TEMPDIR}"
+else
+ TMPDIR1="/tmp"
+fi
+
+TMPC="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.c"
+TMPO="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.o"
+TMPE="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}"
+TMPS="${TMPDIR1}/qemu-conf-${RANDOM}-$$-${RANDOM}.S"
+
+# default parameters
+prefix=""
+static="no"
+libdir="lib"
+cross_prefix=""
+cc="gcc"
+host_cc="gcc"
+ar="ar"
+make="make"
+strip="strip"
+cpu=`uname -m`
+target_list="target-i386-dm"
+case "$cpu" in
+ i386|i486|i586|i686|i86pc|BePC)
+ cpu="i386"
+ ;;
+ armv4l)
+ cpu="armv4l"
+ ;;
+ alpha)
+ cpu="alpha"
+ ;;
+ "Power Macintosh"|ppc|ppc64)
+ cpu="powerpc"
+ ;;
+ mips)
+ cpu="mips"
+ ;;
+ s390)
+ cpu="s390"
+ ;;
+ sparc)
+ cpu="sparc"
+ ;;
+ sparc64)
+ cpu="sparc64"
+ ;;
+ ia64)
+ cpu="ia64"
+ ;;
+ m68k)
+ cpu="m68k"
+ ;;
+ x86_64|amd64)
+ cpu="amd64"
+ libdir="lib64"
+ ;;
+ *)
+ cpu="unknown"
+ ;;
+esac
+gprof="no"
+bigendian="no"
+mingw32="no"
+EXESUF=""
+gdbstub="no"
+slirp="no"
+adlib="no"
+oss="no"
+fmod="no"
+fmod_lib=""
+fmod_inc=""
+
+# OS specific
+targetos=`uname -s`
+case $targetos in
+MINGW32*)
+mingw32="yes"
+;;
+FreeBSD)
+bsd="yes"
+oss="yes"
+;;
+NetBSD)
+bsd="yes"
+oss="yes"
+;;
+OpenBSD)
+bsd="yes"
+oss="yes"
+;;
+Darwin)
+bsd="yes"
+darwin="yes"
+;;
+*)
+oss="yes"
+;;
+esac
+
+if [ "$bsd" = "yes" ] ; then
+ if [ ! "$darwin" = "yes" ] ; then
+ make="gmake"
+ fi
+ target_list="i386-softmmu ppc-softmmu sparc-softmmu"
+fi
+
+# find source path
+# XXX: we assume an absolute path is given when launching configure,
+# except in './configure' case.
+source_path=${0%configure}
+source_path=${source_path%/}
+source_path_used="yes"
+if test -z "$source_path" -o "$source_path" = "." ; then
+ source_path=`pwd`
+ source_path_used="no"
+fi
+
+for opt do
+ case "$opt" in
+ --prefix=*) prefix=`echo $opt | cut -d '=' -f 2`
+ ;;
+ --interp-prefix=*) interp_prefix=`echo $opt | cut -d '=' -f 2`
+ ;;
+ --source-path=*) source_path=`echo $opt | cut -d '=' -f 2`
+ ;;
+ --cross-prefix=*) cross_prefix=`echo $opt | cut -d '=' -f 2`
+ ;;
+ --cc=*) cc=`echo $opt | cut -d '=' -f 2`
+ ;;
+ --make=*) make=`echo $opt | cut -d '=' -f 2`
+ ;;
+ --extra-cflags=*) CFLAGS="${opt#--extra-cflags=}"
+ ;;
+ --extra-ldflags=*) LDFLAGS="${opt#--extra-ldflags=}"
+ ;;
+ --extra-libs=*) extralibs=${opt#--extra-libs=}
+ ;;
+ --cpu=*) cpu=`echo $opt | cut -d '=' -f 2`
+ ;;
+ --target-list=*) target_list=${opt#--target-list=}
+ ;;
+ --enable-gprof) gprof="yes"
+ ;;
+ --static) static="yes"
+ ;;
+ --disable-sdl) sdl="no"
+ ;;
+ --enable-fmod) fmod="yes"
+ ;;
+ --fmod-lib=*) fmod_lib=${opt#--fmod-lib=}
+ ;;
+ --fmod-inc=*) fmod_inc=${opt#--fmod-inc=}
+ ;;
+ --disable-vnc) vnc="no"
+ ;;
+ --enable-mingw32) mingw32="yes" ; cross_prefix="i386-mingw32-"
+ ;;
+ --disable-slirp) slirp="no"
+ ;;
+ --enable-adlib) adlib="yes"
+ ;;
+ esac
+done
+
+# Checking for CFLAGS
+if test -z "$CFLAGS"; then
+ CFLAGS="-O2"
+fi
+
+cc="${cross_prefix}${cc}"
+ar="${cross_prefix}${ar}"
+strip="${cross_prefix}${strip}"
+
+if test "$mingw32" = "yes" ; then
+ target_list="i386-softmmu ppc-softmmu sparc-softmmu"
+ EXESUF=".exe"
+ gdbstub="no"
+ oss="no"
+fi
+
+if test -z "$cross_prefix" ; then
+
+# ---
+# big/little endian test
+cat > $TMPC << EOF
+#include <inttypes.h>
+int main(int argc, char ** argv){
+ volatile uint32_t i=0x01234567;
+ return (*((uint8_t*)(&i))) == 0x67;
+}
+EOF
+
+if $cc -o $TMPE $TMPC 2>/dev/null ; then
+$TMPE && bigendian="yes"
+else
+echo big/little test failed
+fi
+
+else
+
+# if cross compiling, cannot launch a program, so make a static guess
+if test "$cpu" = "powerpc" -o "$cpu" = "mips" -o "$cpu" = "s390" -o "$cpu" = "sparc" -o "$cpu" = "sparc64" -o "$cpu" = "m68k"; then
+ bigendian="yes"
+fi
+
+fi
+
+# check gcc options support
+cat > $TMPC <<EOF
+int main(void) {
+}
+EOF
+
+have_gcc3_options="no"
+if $cc -fno-reorder-blocks -fno-optimize-sibling-calls -o $TMPO $TMPC 2> /dev/null ; then
+ have_gcc3_options="yes"
+fi
+
+##########################################
+# VNC probe
+
+if test -z "$vnc"; then
+
+if libvncserver-config --version > /dev/null; then
+ vnc=yes
+else
+ vnc=no
+fi
+
+fi
+
+##########################################
+# SDL probe
+
+sdl_too_old=no
+
+if test -z "$sdl" ; then
+
+sdl_config="sdl-config"
+sdl=no
+sdl_static=no
+
+if test "$mingw32" = "yes" -a ! -z "$cross_prefix" ; then
+# win32 cross compilation case
+ sdl_config="i386-mingw32msvc-sdl-config"
+ sdl=yes
+else
+# normal SDL probe
+cat > $TMPC << EOF
+#include <SDL.h>
+#undef main /* We don't want SDL to override our main() */
+int main( void ) { return SDL_Init (SDL_INIT_VIDEO); }
+EOF
+
+if $cc -o $TMPE `$sdl_config --cflags 2> /dev/null` $TMPC `$sdl_config --libs 2> /dev/null` 2> /dev/null ; then
+_sdlversion=`$sdl_config --version | sed 's/[^0-9]//g'`
+if test "$_sdlversion" -lt 121 ; then
+sdl_too_old=yes
+else
+sdl=yes
+fi
+
+# static link with sdl ?
+if test "$sdl" = "yes" ; then
+aa="no"
+`$sdl_config --static-libs | grep \\\-laa > /dev/null` && aa="yes"
+sdl_static_libs=`$sdl_config --static-libs`
+if [ "$aa" = "yes" ] ; then
+ sdl_static_libs="$sdl_static_libs `aalib-config --static-libs`"
+fi
+
+if $cc -o $TMPE `$sdl_config --cflags 2> /dev/null` $TMPC $sdl_static_libs 2> /dev/null; then
+ sdl_static=yes
+fi
+
+fi # static link
+
+fi # sdl compile test
+
+fi # cross compilation
+fi # -z $sdl
+
+if test x"$1" = x"-h" -o x"$1" = x"--help" ; then
+cat << EOF
+
+Usage: configure [options]
+Options: [defaults in brackets after descriptions]
+
+EOF
+echo "Standard options:"
+echo " --help print this message"
+echo " --prefix=PREFIX install in PREFIX [$prefix]"
+echo " --interp-prefix=PREFIX where to find shared libraries, etc."
+echo " use %M for cpu name [$interp_prefix]"
+echo " --target-list=LIST set target list [$target_list]"
+echo " --disable-vnc disable vnc support (else configure checks"
+echo " for libvncserver-config in your PATH)"
+echo ""
+echo "Advanced options (experts only):"
+echo " --source-path=PATH path of source code [$source_path]"
+echo " --cross-prefix=PREFIX use PREFIX for compile tools [$cross_prefix]"
+echo " --cc=CC use C compiler CC [$cc]"
+echo " --make=MAKE use specified make [$make]"
+echo " --static enable static build [$static]"
+echo " --enable-mingw32 enable Win32 cross compilation with mingw32"
+echo " --enable-fmod enable FMOD audio output driver"
+echo " --fmod-lib path to FMOD library"
+echo " --fmod-inc path to FMOD includes"
+echo ""
+echo "NOTE: The object files are build at the place where configure is launched"
+exit 1
+fi
+
+#installroot=$source_path/../../dist/install
+installroot=
+
+if test "$mingw32" = "yes" ; then
+if test -z "$prefix" ; then
+ prefix="/c/Program Files/Qemu"
+fi
+
+mandir="$prefix"
+datadir="$prefix"
+docdir="$prefix"
+bindir="$prefix"
+configdir=""
+else
+if test -z "$prefix" ; then
+ prefix="usr/local"
+fi
+mandir="$installroot/$prefix/share/man"
+datadir="$installroot/$prefix/share/qemu"
+docdir="$installroot/$prefix/share/doc/qemu"
+bindir="$installroot/$prefix/bin"
+configdir="$installroot/etc/xen"
+fi
+
+echo "Install prefix $prefix"
+echo "BIOS directory $datadir"
+echo "binary directory $bindir"
+if test "$mingw32" = "no" ; then
+echo "Manual directory $mandir"
+fi
+echo "Source path $source_path"
+echo "C compiler $cc"
+echo "make $make"
+echo "host CPU $cpu"
+echo "host big endian $bigendian"
+echo "target list $target_list"
+echo "gprof enabled $gprof"
+echo "static build $static"
+echo "VNC support $vnc"
+echo "SDL support $sdl"
+echo "SDL static link $sdl_static"
+echo "mingw32 support $mingw32"
+echo "Adlib support $adlib"
+echo -n "FMOD support $fmod"
+if test $fmod = "yes"; then
+ echo -n " (lib='$fmod_lib' include='$fmod_inc')"
+fi
+echo ""
+
+if test $sdl_too_old = "yes"; then
+echo "-> Your SDL version is too old - please upgrade to have FFplay/SDL support"
+fi
+if test "$sdl_static" = "no"; then
+ echo "WARNING: cannot compile statically with SDL - qemu-fast won't have a graphical output"
+fi
+
+config_mak="config-host.mak"
+config_h="config-host.h"
+
+#echo "Creating $config_mak and $config_h"
+
+echo "# Automatically generated by configure - do not modify" > $config_mak
+echo "/* Automatically generated by configure - do not modify */" > $config_h
+
+echo "prefix=$prefix" >> $config_mak
+echo "bindir=$bindir" >> $config_mak
+echo "mandir=$mandir" >> $config_mak
+echo "datadir=$datadir" >> $config_mak
+echo "docdir=$docdir" >> $config_mak
+echo "configdir=$configdir" >> $config_mak
+echo "LIBDIR=$libdir" >> $config_mak
+echo "#define CONFIG_QEMU_SHAREDIR \"$datadir\"" >> $config_h
+echo "MAKE=$make" >> $config_mak
+echo "CC=$cc" >> $config_mak
+if test "$have_gcc3_options" = "yes" ; then
+ echo "HAVE_GCC3_OPTIONS=yes" >> $config_mak
+fi
+echo "HOST_CC=$host_cc" >> $config_mak
+echo "AR=$ar" >> $config_mak
+echo "STRIP=$strip -s -R .comment -R .note" >> $config_mak
+echo "CFLAGS=$CFLAGS" >> $config_mak
+echo "LDFLAGS=$LDFLAGS" >> $config_mak
+echo "EXESUF=$EXESUF" >> $config_mak
+
+if test "$bigendian" = "yes" ; then
+ echo "WORDS_BIGENDIAN=yes" >> $config_mak
+ echo "#define WORDS_BIGENDIAN 1" >> $config_h
+fi
+if test "$mingw32" = "yes" ; then
+ echo "CONFIG_WIN32=yes" >> $config_mak
+ echo "#define CONFIG_WIN32 1" >> $config_h
+elif test -f "/usr/include/byteswap.h" ; then
+ echo "#define HAVE_BYTESWAP_H 1" >> $config_h
+fi
+if test "$darwin" = "yes" ; then
+ echo "CONFIG_DARWIN=yes" >> $config_mak
+ echo "#define CONFIG_DARWIN 1" >> $config_h
+fi
+if test "$gdbstub" = "yes" ; then
+ echo "CONFIG_GDBSTUB=yes" >> $config_mak
+ echo "#define CONFIG_GDBSTUB 1" >> $config_h
+fi
+if test "$gprof" = "yes" ; then
+ echo "TARGET_GPROF=yes" >> $config_mak
+ echo "#define HAVE_GPROF 1" >> $config_h
+fi
+if test "$static" = "yes" ; then
+ echo "CONFIG_STATIC=yes" >> $config_mak
+ echo "#define CONFIG_STATIC 1" >> $config_h
+fi
+if test "$slirp" = "yes" ; then
+ echo "CONFIG_SLIRP=yes" >> $config_mak
+ echo "#define CONFIG_SLIRP 1" >> $config_h
+fi
+if test "$adlib" = "yes" ; then
+ echo "CONFIG_ADLIB=yes" >> $config_mak
+ echo "#define CONFIG_ADLIB 1" >> $config_h
+fi
+if test "$oss" = "yes" ; then
+ echo "CONFIG_OSS=yes" >> $config_mak
+ echo "#define CONFIG_OSS 1" >> $config_h
+fi
+if test "$fmod" = "yes" ; then
+ echo "CONFIG_FMOD=yes" >> $config_mak
+ echo "CONFIG_FMOD_LIB=$fmod_lib" >> $config_mak
+ echo "CONFIG_FMOD_INC=$fmod_inc" >> $config_mak
+ echo "#define CONFIG_FMOD 1" >> $config_h
+fi
+echo -n "VERSION=" >>$config_mak
+head $source_path/VERSION >>$config_mak
+echo "" >>$config_mak
+echo -n "#define QEMU_VERSION \"" >> $config_h
+head $source_path/VERSION >> $config_h
+echo "\"" >> $config_h
+
+echo "SRC_PATH=$source_path" >> $config_mak
+echo "TARGET_DIRS=$target_list" >> $config_mak
+
+# XXX: suppress that
+if [ "$bsd" = "yes" ] ; then
+ echo "#define O_LARGEFILE 0" >> $config_h
+ echo "#define MAP_ANONYMOUS MAP_ANON" >> $config_h
+ echo "#define _BSD 1" >> $config_h
+fi
+
+if test "$vnc" = "yes"; then
+ echo "CONFIG_VNC=yes" >> $config_mak
+ vnc_cflags=`libvncserver-config --cflags`
+ if [ -z $vnc_cflags ]; then
+ vnc_cflags="/usr/include"
+ fi
+ echo "VNC_CFLAGS=$vnc_cflags" >> $config_mak
+fi
+
+if test "$sdl" = "yes"; then
+ echo "CONFIG_SDL=yes" >> $config_mak
+ echo "SDL_CFLAGS=`$sdl_config --cflags`" >> $config_mak
+fi
+
+for target in $target_list; do
+
+target_dir="$target"
+config_mak=$target_dir/config.mak
+config_h=$target_dir/config.h
+target_cpu=`echo $target | cut -d '-' -f 2`
+[ "$target_cpu" = "ppc" ] && target_bigendian=yes
+target_softmmu="no"
+if expr $target : '.*-softmmu' > /dev/null ; then
+ target_softmmu="yes"
+fi
+target_user_only="no"
+if expr $target : '.*-user' > /dev/null ; then
+ target_user_only="yes"
+fi
+#echo "Creating $config_mak, $config_h and $target_dir/Makefile"
+
+mkdir -p $target_dir
+if test "$target" = "arm-user" ; then
+ mkdir -p $target_dir/nwfpe
+fi
+if test "$target_user_only" = "no" ; then
+ mkdir -p $target_dir/slirp
+fi
+
+ln -sf $source_path/Makefile.target $target_dir/Makefile
+
+echo "# Automatically generated by configure - do not modify" > $config_mak
+echo "/* Automatically generated by configure - do not modify */" > $config_h
+
+
+echo "include ../config-host.mak" >> $config_mak
+echo "#include \"../config-host.h\"" >> $config_h
+
+if test "$target_cpu" = "i386" ; then
+ echo "TARGET_ARCH=i386" >> $config_mak
+ echo "#define TARGET_ARCH \"i386\"" >> $config_h
+ echo "#define TARGET_I386 1" >> $config_h
+fi
+
+interp_prefix1=`echo "$interp_prefix" | sed "s/%M/$target_cpu/g"`
+echo "#define CONFIG_QEMU_PREFIX \"$interp_prefix1\"" >> $config_h
+
+if test "$target_bigendian" = "yes" ; then
+ echo "TARGET_WORDS_BIGENDIAN=yes" >> $config_mak
+ echo "#define TARGET_WORDS_BIGENDIAN 1" >> $config_h
+fi
+if test "$target_softmmu" = "yes" ; then
+ echo "CONFIG_SOFTMMU=yes" >> $config_mak
+ echo "#define CONFIG_SOFTMMU 1" >> $config_h
+fi
+if test "$target_user_only" = "yes" ; then
+ echo "CONFIG_USER_ONLY=yes" >> $config_mak
+ echo "#define CONFIG_USER_ONLY 1" >> $config_h
+fi
+
+if test "$target_user_only" = "no"; then
+ if test "$vnc" = "yes"; then
+ echo "#define CONFIG_VNC 1" >> $config_h
+ echo "CONFIG_VNC=yes" >> $config_mak
+ echo "VNC_CFLAGS=`libvncserver-config --cflags`" >> $config_mak
+ echo "VNC_LIBS=`libvncserver-config --libs`" >> $config_mak
+ fi
+fi
+
+# sdl defines
+
+if test "$sdl" = "yes" -a "$target_user_only" = "no"; then
+ if test "$target_softmmu" = "no" -o "$static" = "yes"; then
+ sdl1=$sdl_static
+ else
+ sdl1=$sdl
+ fi
+ if test "$sdl1" = "yes" ; then
+ echo "#define CONFIG_SDL 1" >> $config_h
+ echo "CONFIG_SDL=yes" >> $config_mak
+ if test "$target_softmmu" = "no" -o "$static" = "yes"; then
+ echo "SDL_LIBS=$sdl_static_libs" >> $config_mak
+ else
+ echo "SDL_LIBS=`$sdl_config --libs`" >> $config_mak
+ fi
+ echo -n "SDL_CFLAGS=`$sdl_config --cflags`" >> $config_mak
+ if [ "${aa}" = "yes" ] ; then
+ echo -n " `aalib-config --cflags`" >> $config_mak ;
+ fi
+ echo "" >> $config_mak
+ fi
+fi
+
+done # for target in $targets
+
+# build tree in object directory if source path is different from current one
+if test "$source_path_used" = "yes" ; then
+ DIRS="tests"
+ FILES="Makefile tests/Makefile"
+ for dir in $DIRS ; do
+ mkdir -p $dir
+ done
+ for f in $FILES ; do
+ ln -sf $source_path/$f $f
+ done
+fi
+
+rm -f $TMPO $TMPC $TMPE $TMPS
--- /dev/null
+/*
+ * QEMU graphical console
+ *
+ * Copyright (c) 2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+
+#define DEFAULT_BACKSCROLL 512
+#define MAX_CONSOLES 12
+
+#define RGBA(r, g, b, a) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
+#define RGB(r, g, b) RGBA(r, g, b, 0xff)
+
+typedef struct TextCell {
+ uint8_t ch;
+ uint8_t bgcol:4;
+ uint8_t fgcol:4;
+} TextCell;
+
+#define MAX_ESC_PARAMS 3
+
+enum TTYState {
+ TTY_STATE_NORM,
+ TTY_STATE_ESC,
+ TTY_STATE_CSI,
+};
+
+struct TextConsole {
+ int text_console; /* true if text console */
+ DisplayState *ds;
+ int g_width, g_height;
+ int width;
+ int height;
+ int total_height;
+ int backscroll_height;
+ int fgcol;
+ int bgcol;
+ int x, y;
+ int y_displayed;
+ int y_base;
+ TextCell *cells;
+
+ enum TTYState state;
+ int esc_params[MAX_ESC_PARAMS];
+ int nb_esc_params;
+
+ /* kbd read handler */
+ IOReadHandler *fd_read;
+ void *fd_opaque;
+};
+
+static TextConsole *active_console;
+static TextConsole *consoles[MAX_CONSOLES];
+static int nb_consoles = 0;
+
+/* convert a RGBA color to a color index usable in graphic primitives */
+static unsigned int vga_get_color(DisplayState *ds, unsigned int rgba)
+{
+ unsigned int r, g, b, color;
+
+ switch(ds->depth) {
+#if 0
+ case 8:
+ r = (rgba >> 16) & 0xff;
+ g = (rgba >> 8) & 0xff;
+ b = (rgba) & 0xff;
+ color = (rgb_to_index[r] * 6 * 6) +
+ (rgb_to_index[g] * 6) +
+ (rgb_to_index[b]);
+ break;
+#endif
+ case 15:
+ r = (rgba >> 16) & 0xff;
+ g = (rgba >> 8) & 0xff;
+ b = (rgba) & 0xff;
+ color = ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
+ break;
+ case 16:
+ r = (rgba >> 16) & 0xff;
+ g = (rgba >> 8) & 0xff;
+ b = (rgba) & 0xff;
+ color = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
+ break;
+ case 32:
+ default:
+ color = rgba;
+ break;
+ }
+ return color;
+}
+
+static void vga_fill_rect (DisplayState *ds,
+ int posx, int posy, int width, int height, uint32_t color)
+{
+ uint8_t *d, *d1;
+ int x, y, bpp;
+
+ bpp = (ds->depth + 7) >> 3;
+ d1 = ds->data +
+ ds->linesize * posy + bpp * posx;
+ for (y = 0; y < height; y++) {
+ d = d1;
+ switch(bpp) {
+ case 1:
+ for (x = 0; x < width; x++) {
+ *((uint8_t *)d) = color;
+ d++;
+ }
+ break;
+ case 2:
+ for (x = 0; x < width; x++) {
+ *((uint16_t *)d) = color;
+ d += 2;
+ }
+ break;
+ case 4:
+ for (x = 0; x < width; x++) {
+ *((uint32_t *)d) = color;
+ d += 4;
+ }
+ break;
+ }
+ d1 += ds->linesize;
+ }
+}
+
+/* copy from (xs, ys) to (xd, yd) a rectangle of size (w, h) */
+static void vga_bitblt(DisplayState *ds, int xs, int ys, int xd, int yd, int w, int h)
+{
+ const uint8_t *s;
+ uint8_t *d;
+ int wb, y, bpp;
+
+ bpp = (ds->depth + 7) >> 3;
+ wb = w * bpp;
+ if (yd <= ys) {
+ s = ds->data +
+ ds->linesize * ys + bpp * xs;
+ d = ds->data +
+ ds->linesize * yd + bpp * xd;
+ for (y = 0; y < h; y++) {
+ memmove(d, s, wb);
+ d += ds->linesize;
+ s += ds->linesize;
+ }
+ } else {
+ s = ds->data +
+ ds->linesize * (ys + h - 1) + bpp * xs;
+ d = ds->data +
+ ds->linesize * (yd + h - 1) + bpp * xd;
+ for (y = 0; y < h; y++) {
+ memmove(d, s, wb);
+ d -= ds->linesize;
+ s -= ds->linesize;
+ }
+ }
+}
+
+/***********************************************************/
+/* basic char display */
+
+#define FONT_HEIGHT 16
+#define FONT_WIDTH 8
+
+#include "vgafont.h"
+
+#define cbswap_32(__x) \
+((uint32_t)( \
+ (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
+ (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \
+ (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \
+ (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
+
+#ifdef WORDS_BIGENDIAN
+#define PAT(x) x
+#else
+#define PAT(x) cbswap_32(x)
+#endif
+
+static const uint32_t dmask16[16] = {
+ PAT(0x00000000),
+ PAT(0x000000ff),
+ PAT(0x0000ff00),
+ PAT(0x0000ffff),
+ PAT(0x00ff0000),
+ PAT(0x00ff00ff),
+ PAT(0x00ffff00),
+ PAT(0x00ffffff),
+ PAT(0xff000000),
+ PAT(0xff0000ff),
+ PAT(0xff00ff00),
+ PAT(0xff00ffff),
+ PAT(0xffff0000),
+ PAT(0xffff00ff),
+ PAT(0xffffff00),
+ PAT(0xffffffff),
+};
+
+static const uint32_t dmask4[4] = {
+ PAT(0x00000000),
+ PAT(0x0000ffff),
+ PAT(0xffff0000),
+ PAT(0xffffffff),
+};
+
+static uint32_t color_table[8];
+
+static const uint32_t color_table_rgb[8] = {
+ RGB(0x00, 0x00, 0x00),
+ RGB(0xff, 0x00, 0x00),
+ RGB(0x00, 0xff, 0x00),
+ RGB(0xff, 0xff, 0x00),
+ RGB(0x00, 0x00, 0xff),
+ RGB(0xff, 0x00, 0xff),
+ RGB(0x00, 0xff, 0xff),
+ RGB(0xff, 0xff, 0xff),
+};
+
+static inline unsigned int col_expand(DisplayState *ds, unsigned int col)
+{
+ switch(ds->depth) {
+ case 8:
+ col |= col << 8;
+ col |= col << 16;
+ break;
+ case 15:
+ case 16:
+ col |= col << 16;
+ break;
+ default:
+ break;
+ }
+
+ return col;
+}
+
+static void vga_putcharxy(DisplayState *ds, int x, int y, int ch,
+ unsigned int fgcol, unsigned int bgcol)
+{
+ uint8_t *d;
+ const uint8_t *font_ptr;
+ unsigned int font_data, linesize, xorcol, bpp;
+ int i;
+
+ bpp = (ds->depth + 7) >> 3;
+ d = ds->data +
+ ds->linesize * y * FONT_HEIGHT + bpp * x * FONT_WIDTH;
+ linesize = ds->linesize;
+ font_ptr = vgafont16 + FONT_HEIGHT * ch;
+ xorcol = bgcol ^ fgcol;
+ switch(ds->depth) {
+ case 8:
+ for(i = 0; i < FONT_HEIGHT; i++) {
+ font_data = *font_ptr++;
+ ((uint32_t *)d)[0] = (dmask16[(font_data >> 4)] & xorcol) ^ bgcol;
+ ((uint32_t *)d)[1] = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol;
+ d += linesize;
+ }
+ break;
+ case 16:
+ case 15:
+ for(i = 0; i < FONT_HEIGHT; i++) {
+ font_data = *font_ptr++;
+ ((uint32_t *)d)[0] = (dmask4[(font_data >> 6)] & xorcol) ^ bgcol;
+ ((uint32_t *)d)[1] = (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol;
+ ((uint32_t *)d)[2] = (dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol;
+ ((uint32_t *)d)[3] = (dmask4[(font_data >> 0) & 3] & xorcol) ^ bgcol;
+ d += linesize;
+ }
+ break;
+ case 32:
+ for(i = 0; i < FONT_HEIGHT; i++) {
+ font_data = *font_ptr++;
+ ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol;
+ ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol;
+ ((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol;
+ ((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol;
+ ((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol;
+ ((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol;
+ ((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol;
+ ((uint32_t *)d)[7] = (-((font_data >> 0) & 1) & xorcol) ^ bgcol;
+ d += linesize;
+ }
+ break;
+ }
+}
+
+static void text_console_resize(TextConsole *s)
+{
+ TextCell *cells, *c, *c1;
+ int w1, x, y, last_width;
+
+ last_width = s->width;
+ s->width = s->g_width / FONT_WIDTH;
+ s->height = s->g_height / FONT_HEIGHT;
+
+ w1 = last_width;
+ if (s->width < w1)
+ w1 = s->width;
+
+ cells = qemu_malloc(s->width * s->total_height * sizeof(TextCell));
+ for(y = 0; y < s->total_height; y++) {
+ c = &cells[y * s->width];
+ if (w1 > 0) {
+ c1 = &s->cells[y * last_width];
+ for(x = 0; x < w1; x++) {
+ *c++ = *c1++;
+ }
+ }
+ for(x = w1; x < s->width; x++) {
+ c->ch = ' ';
+ c->fgcol = 7;
+ c->bgcol = 0;
+ c++;
+ }
+ }
+ qemu_free(s->cells);
+ s->cells = cells;
+}
+
+static void update_xy(TextConsole *s, int x, int y)
+{
+ TextCell *c;
+ int y1, y2;
+
+ if (s == active_console) {
+ y1 = (s->y_base + y) % s->total_height;
+ y2 = y1 - s->y_displayed;
+ if (y2 < 0)
+ y2 += s->total_height;
+ if (y2 < s->height) {
+ c = &s->cells[y1 * s->width + x];
+ vga_putcharxy(s->ds, x, y2, c->ch,
+ color_table[c->fgcol], color_table[c->bgcol]);
+ dpy_update(s->ds, x * FONT_WIDTH, y2 * FONT_HEIGHT,
+ FONT_WIDTH, FONT_HEIGHT);
+ }
+ }
+}
+
+static void console_show_cursor(TextConsole *s, int show)
+{
+ TextCell *c;
+ int y, y1;
+
+ if (s == active_console) {
+ y1 = (s->y_base + s->y) % s->total_height;
+ y = y1 - s->y_displayed;
+ if (y < 0)
+ y += s->total_height;
+ if (y < s->height) {
+ c = &s->cells[y1 * s->width + s->x];
+ if (show) {
+ vga_putcharxy(s->ds, s->x, y, c->ch,
+ color_table[0], color_table[7]);
+ } else {
+ vga_putcharxy(s->ds, s->x, y, c->ch,
+ color_table[c->fgcol], color_table[c->bgcol]);
+ }
+ dpy_update(s->ds, s->x * FONT_WIDTH, y * FONT_HEIGHT,
+ FONT_WIDTH, FONT_HEIGHT);
+ }
+ }
+}
+
+static void console_refresh(TextConsole *s)
+{
+ TextCell *c;
+ int x, y, y1;
+
+ if (s != active_console)
+ return;
+
+ vga_fill_rect(s->ds, 0, 0, s->ds->width, s->ds->height,
+ color_table[0]);
+ y1 = s->y_displayed;
+ for(y = 0; y < s->height; y++) {
+ c = s->cells + y1 * s->width;
+ for(x = 0; x < s->width; x++) {
+ vga_putcharxy(s->ds, x, y, c->ch,
+ color_table[c->fgcol], color_table[c->bgcol]);
+ c++;
+ }
+ if (++y1 == s->total_height)
+ y1 = 0;
+ }
+ dpy_update(s->ds, 0, 0, s->ds->width, s->ds->height);
+ console_show_cursor(s, 1);
+}
+
+static void console_scroll(int ydelta)
+{
+ TextConsole *s;
+ int i, y1;
+
+ s = active_console;
+ if (!s || !s->text_console)
+ return;
+
+ if (ydelta > 0) {
+ for(i = 0; i < ydelta; i++) {
+ if (s->y_displayed == s->y_base)
+ break;
+ if (++s->y_displayed == s->total_height)
+ s->y_displayed = 0;
+ }
+ } else {
+ ydelta = -ydelta;
+ i = s->backscroll_height;
+ if (i > s->total_height - s->height)
+ i = s->total_height - s->height;
+ y1 = s->y_base - i;
+ if (y1 < 0)
+ y1 += s->total_height;
+ for(i = 0; i < ydelta; i++) {
+ if (s->y_displayed == y1)
+ break;
+ if (--s->y_displayed < 0)
+ s->y_displayed = s->total_height - 1;
+ }
+ }
+ console_refresh(s);
+}
+
+static void console_put_lf(TextConsole *s)
+{
+ TextCell *c;
+ int x, y1;
+
+ s->x = 0;
+ s->y++;
+ if (s->y >= s->height) {
+ s->y = s->height - 1;
+
+ if (s->y_displayed == s->y_base) {
+ if (++s->y_displayed == s->total_height)
+ s->y_displayed = 0;
+ }
+ if (++s->y_base == s->total_height)
+ s->y_base = 0;
+ if (s->backscroll_height < s->total_height)
+ s->backscroll_height++;
+ y1 = (s->y_base + s->height - 1) % s->total_height;
+ c = &s->cells[y1 * s->width];
+ for(x = 0; x < s->width; x++) {
+ c->ch = ' ';
+ c->fgcol = s->fgcol;
+ c->bgcol = s->bgcol;
+ c++;
+ }
+ if (s == active_console && s->y_displayed == s->y_base) {
+ vga_bitblt(s->ds, 0, FONT_HEIGHT, 0, 0,
+ s->width * FONT_WIDTH,
+ (s->height - 1) * FONT_HEIGHT);
+ vga_fill_rect(s->ds, 0, (s->height - 1) * FONT_HEIGHT,
+ s->width * FONT_WIDTH, FONT_HEIGHT,
+ color_table[s->bgcol]);
+ dpy_update(s->ds, 0, 0,
+ s->width * FONT_WIDTH, s->height * FONT_HEIGHT);
+ }
+ }
+}
+
+static void console_putchar(TextConsole *s, int ch)
+{
+ TextCell *c;
+ int y1, i, x;
+
+ switch(s->state) {
+ case TTY_STATE_NORM:
+ switch(ch) {
+ case '\r':
+ s->x = 0;
+ break;
+ case '\n':
+ console_put_lf(s);
+ break;
+ case 27:
+ s->state = TTY_STATE_ESC;
+ break;
+ default:
+ y1 = (s->y_base + s->y) % s->total_height;
+ c = &s->cells[y1 * s->width + s->x];
+ c->ch = ch;
+ c->fgcol = s->fgcol;
+ c->bgcol = s->bgcol;
+ update_xy(s, s->x, s->y);
+ s->x++;
+ if (s->x >= s->width)
+ console_put_lf(s);
+ break;
+ }
+ break;
+ case TTY_STATE_ESC:
+ if (ch == '[') {
+ for(i=0;i<MAX_ESC_PARAMS;i++)
+ s->esc_params[i] = 0;
+ s->nb_esc_params = 0;
+ s->state = TTY_STATE_CSI;
+ } else {
+ s->state = TTY_STATE_NORM;
+ }
+ break;
+ case TTY_STATE_CSI:
+ if (ch >= '0' && ch <= '9') {
+ if (s->nb_esc_params < MAX_ESC_PARAMS) {
+ s->esc_params[s->nb_esc_params] =
+ s->esc_params[s->nb_esc_params] * 10 + ch - '0';
+ }
+ } else {
+ s->nb_esc_params++;
+ if (ch == ';')
+ break;
+ s->state = TTY_STATE_NORM;
+ switch(ch) {
+ case 'D':
+ if (s->x > 0)
+ s->x--;
+ break;
+ case 'C':
+ if (s->x < (s->width - 1))
+ s->x++;
+ break;
+ case 'K':
+ /* clear to eol */
+ y1 = (s->y_base + s->y) % s->total_height;
+ for(x = s->x; x < s->width; x++) {
+ c = &s->cells[y1 * s->width + x];
+ c->ch = ' ';
+ c->fgcol = s->fgcol;
+ c->bgcol = s->bgcol;
+ c++;
+ update_xy(s, x, s->y);
+ }
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+ }
+}
+
+void console_select(unsigned int index)
+{
+ TextConsole *s;
+
+ if (index >= MAX_CONSOLES)
+ return;
+ s = consoles[index];
+ if (s) {
+ active_console = s;
+ if (s->text_console) {
+ if (s->g_width != s->ds->width ||
+ s->g_height != s->ds->height) {
+ s->g_width = s->ds->width;
+ s->g_height = s->ds->height;
+ text_console_resize(s);
+ }
+ console_refresh(s);
+ }
+ }
+}
+
+static int console_puts(CharDriverState *chr, const uint8_t *buf, int len)
+{
+ TextConsole *s = chr->opaque;
+ int i;
+
+ console_show_cursor(s, 0);
+ for(i = 0; i < len; i++) {
+ console_putchar(s, buf[i]);
+ }
+ console_show_cursor(s, 1);
+ return len;
+}
+
+static void console_chr_add_read_handler(CharDriverState *chr,
+ IOCanRWHandler *fd_can_read,
+ IOReadHandler *fd_read, void *opaque)
+{
+ TextConsole *s = chr->opaque;
+ s->fd_read = fd_read;
+ s->fd_opaque = opaque;
+}
+
+static void console_send_event(CharDriverState *chr, int event)
+{
+ TextConsole *s = chr->opaque;
+ int i;
+
+ if (event == CHR_EVENT_FOCUS) {
+ for(i = 0; i < nb_consoles; i++) {
+ if (consoles[i] == s) {
+ console_select(i);
+ break;
+ }
+ }
+ }
+}
+
+/* called when an ascii key is pressed */
+void kbd_put_keysym(int keysym)
+{
+ TextConsole *s;
+ uint8_t buf[16], *q;
+ int c;
+
+ s = active_console;
+ if (!s || !s->text_console)
+ return;
+
+ switch(keysym) {
+ case QEMU_KEY_CTRL_UP:
+ console_scroll(-1);
+ break;
+ case QEMU_KEY_CTRL_DOWN:
+ console_scroll(1);
+ break;
+ case QEMU_KEY_CTRL_PAGEUP:
+ console_scroll(-10);
+ break;
+ case QEMU_KEY_CTRL_PAGEDOWN:
+ console_scroll(10);
+ break;
+ default:
+ if (s->fd_read) {
+ /* convert the QEMU keysym to VT100 key string */
+ q = buf;
+ if (keysym >= 0xe100 && keysym <= 0xe11f) {
+ *q++ = '\033';
+ *q++ = '[';
+ c = keysym - 0xe100;
+ if (c >= 10)
+ *q++ = '0' + (c / 10);
+ *q++ = '0' + (c % 10);
+ *q++ = '~';
+ } else if (keysym >= 0xe120 && keysym <= 0xe17f) {
+ *q++ = '\033';
+ *q++ = '[';
+ *q++ = keysym & 0xff;
+ } else {
+ *q++ = keysym;
+ }
+ s->fd_read(s->fd_opaque, buf, q - buf);
+ }
+ break;
+ }
+}
+
+TextConsole *graphic_console_init(DisplayState *ds)
+{
+ TextConsole *s;
+
+ if (nb_consoles >= MAX_CONSOLES)
+ return NULL;
+ s = qemu_mallocz(sizeof(TextConsole));
+ if (!s) {
+ return NULL;
+ }
+ if (!active_console)
+ active_console = s;
+ s->ds = ds;
+ consoles[nb_consoles++] = s;
+ return s;
+}
+
+int is_active_console(TextConsole *s)
+{
+ return s == active_console;
+}
+
+CharDriverState *text_console_init(DisplayState *ds)
+{
+ CharDriverState *chr;
+ TextConsole *s;
+ int i;
+ static int color_inited;
+
+ chr = qemu_mallocz(sizeof(CharDriverState));
+ if (!chr)
+ return NULL;
+ s = graphic_console_init(ds);
+ if (!s) {
+ free(chr);
+ return NULL;
+ }
+ s->text_console = 1;
+ chr->opaque = s;
+ chr->chr_write = console_puts;
+ chr->chr_add_read_handler = console_chr_add_read_handler;
+ chr->chr_send_event = console_send_event;
+
+ if (!color_inited) {
+ color_inited = 1;
+ for(i = 0; i < 8; i++) {
+ color_table[i] = col_expand(s->ds,
+ vga_get_color(s->ds, color_table_rgb[i]));
+ }
+ }
+ s->y_displayed = 0;
+ s->y_base = 0;
+ s->total_height = DEFAULT_BACKSCROLL;
+ s->x = 0;
+ s->y = 0;
+ s->fgcol = 7;
+ s->bgcol = 0;
+ s->g_width = s->ds->width;
+ s->g_height = s->ds->height;
+ text_console_resize(s);
+
+ return chr;
+}
--- /dev/null
+/*
+ * defines common to all virtual CPUs
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef CPU_ALL_H
+#define CPU_ALL_H
+
+#if defined(__arm__) || defined(__sparc__)
+#define WORDS_ALIGNED
+#endif
+
+/* some important defines:
+ *
+ * WORDS_ALIGNED : if defined, the host cpu can only make word aligned
+ * memory accesses.
+ *
+ * WORDS_BIGENDIAN : if defined, the host cpu is big endian and
+ * otherwise little endian.
+ *
+ * (TARGET_WORDS_ALIGNED : same for target cpu (not supported yet))
+ *
+ * TARGET_WORDS_BIGENDIAN : same for target cpu
+ */
+
+#include "bswap.h"
+
+#if defined(WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
+#define BSWAP_NEEDED
+#endif
+
+#ifdef BSWAP_NEEDED
+
+static inline uint16_t tswap16(uint16_t s)
+{
+ return bswap16(s);
+}
+
+static inline uint32_t tswap32(uint32_t s)
+{
+ return bswap32(s);
+}
+
+static inline uint64_t tswap64(uint64_t s)
+{
+ return bswap64(s);
+}
+
+static inline void tswap16s(uint16_t *s)
+{
+ *s = bswap16(*s);
+}
+
+static inline void tswap32s(uint32_t *s)
+{
+ *s = bswap32(*s);
+}
+
+static inline void tswap64s(uint64_t *s)
+{
+ *s = bswap64(*s);
+}
+
+#else
+
+static inline uint16_t tswap16(uint16_t s)
+{
+ return s;
+}
+
+static inline uint32_t tswap32(uint32_t s)
+{
+ return s;
+}
+
+static inline uint64_t tswap64(uint64_t s)
+{
+ return s;
+}
+
+static inline void tswap16s(uint16_t *s)
+{
+}
+
+static inline void tswap32s(uint32_t *s)
+{
+}
+
+static inline void tswap64s(uint64_t *s)
+{
+}
+
+#endif
+
+#if TARGET_LONG_SIZE == 4
+#define tswapl(s) tswap32(s)
+#define tswapls(s) tswap32s((uint32_t *)(s))
+#else
+#define tswapl(s) tswap64(s)
+#define tswapls(s) tswap64s((uint64_t *)(s))
+#endif
+
+/* NOTE: arm is horrible as double 32 bit words are stored in big endian ! */
+typedef union {
+ double d;
+#if !defined(WORDS_BIGENDIAN) && !defined(__arm__)
+ struct {
+ uint32_t lower;
+ uint32_t upper;
+ } l;
+#else
+ struct {
+ uint32_t upper;
+ uint32_t lower;
+ } l;
+#endif
+ uint64_t ll;
+} CPU_DoubleU;
+
+/* CPU memory access without any memory or io remapping */
+
+/*
+ * the generic syntax for the memory accesses is:
+ *
+ * load: ld{type}{sign}{size}{endian}_{access_type}(ptr)
+ *
+ * store: st{type}{size}{endian}_{access_type}(ptr, val)
+ *
+ * type is:
+ * (empty): integer access
+ * f : float access
+ *
+ * sign is:
+ * (empty): for floats or 32 bit size
+ * u : unsigned
+ * s : signed
+ *
+ * size is:
+ * b: 8 bits
+ * w: 16 bits
+ * l: 32 bits
+ * q: 64 bits
+ *
+ * endian is:
+ * (empty): target cpu endianness or 8 bit access
+ * r : reversed target cpu endianness (not implemented yet)
+ * be : big endian (not implemented yet)
+ * le : little endian (not implemented yet)
+ *
+ * access_type is:
+ * raw : host memory access
+ * user : user mode access using soft MMU
+ * kernel : kernel mode access using soft MMU
+ */
+static inline int ldub_raw(void *ptr)
+{
+ return *(uint8_t *)ptr;
+}
+
+static inline int ldsb_raw(void *ptr)
+{
+ return *(int8_t *)ptr;
+}
+
+static inline void stb_raw(void *ptr, int v)
+{
+ *(uint8_t *)ptr = v;
+}
+
+/* NOTE: on arm, putting 2 in /proc/sys/debug/alignment so that the
+ kernel handles unaligned load/stores may give better results, but
+ it is a system wide setting : bad */
+#if !defined(TARGET_WORDS_BIGENDIAN) && (defined(WORDS_BIGENDIAN) || defined(WORDS_ALIGNED))
+
+/* conservative code for little endian unaligned accesses */
+static inline int lduw_raw(void *ptr)
+{
+#ifdef __powerpc__
+ int val;
+ __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
+ return val;
+#else
+ uint8_t *p = ptr;
+ return p[0] | (p[1] << 8);
+#endif
+}
+
+static inline int ldsw_raw(void *ptr)
+{
+#ifdef __powerpc__
+ int val;
+ __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
+ return (int16_t)val;
+#else
+ uint8_t *p = ptr;
+ return (int16_t)(p[0] | (p[1] << 8));
+#endif
+}
+
+static inline int ldl_raw(void *ptr)
+{
+#ifdef __powerpc__
+ int val;
+ __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (ptr));
+ return val;
+#else
+ uint8_t *p = ptr;
+ return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
+#endif
+}
+
+static inline uint64_t ldq_raw(void *ptr)
+{
+ uint8_t *p = ptr;
+ uint32_t v1, v2;
+ v1 = ldl_raw(p);
+ v2 = ldl_raw(p + 4);
+ return v1 | ((uint64_t)v2 << 32);
+}
+
+static inline void stw_raw(void *ptr, int v)
+{
+#ifdef __powerpc__
+ __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*(uint16_t *)ptr) : "r" (v), "r" (ptr));
+#else
+ uint8_t *p = ptr;
+ p[0] = v;
+ p[1] = v >> 8;
+#endif
+}
+
+static inline void stl_raw(void *ptr, int v)
+{
+#ifdef __powerpc__
+ __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*(uint32_t *)ptr) : "r" (v), "r" (ptr));
+#else
+ uint8_t *p = ptr;
+ p[0] = v;
+ p[1] = v >> 8;
+ p[2] = v >> 16;
+ p[3] = v >> 24;
+#endif
+}
+
+static inline void stq_raw(void *ptr, uint64_t v)
+{
+ uint8_t *p = ptr;
+ stl_raw(p, (uint32_t)v);
+ stl_raw(p + 4, v >> 32);
+}
+
+/* float access */
+
+static inline float ldfl_raw(void *ptr)
+{
+ union {
+ float f;
+ uint32_t i;
+ } u;
+ u.i = ldl_raw(ptr);
+ return u.f;
+}
+
+static inline void stfl_raw(void *ptr, float v)
+{
+ union {
+ float f;
+ uint32_t i;
+ } u;
+ u.f = v;
+ stl_raw(ptr, u.i);
+}
+
+static inline double ldfq_raw(void *ptr)
+{
+ CPU_DoubleU u;
+ u.l.lower = ldl_raw(ptr);
+ u.l.upper = ldl_raw(ptr + 4);
+ return u.d;
+}
+
+static inline void stfq_raw(void *ptr, double v)
+{
+ CPU_DoubleU u;
+ u.d = v;
+ stl_raw(ptr, u.l.lower);
+ stl_raw(ptr + 4, u.l.upper);
+}
+
+#elif defined(TARGET_WORDS_BIGENDIAN) && (!defined(WORDS_BIGENDIAN) || defined(WORDS_ALIGNED))
+
+static inline int lduw_raw(void *ptr)
+{
+#if defined(__i386__)
+ int val;
+ asm volatile ("movzwl %1, %0\n"
+ "xchgb %b0, %h0\n"
+ : "=q" (val)
+ : "m" (*(uint16_t *)ptr));
+ return val;
+#else
+ uint8_t *b = (uint8_t *) ptr;
+ return ((b[0] << 8) | b[1]);
+#endif
+}
+
+static inline int ldsw_raw(void *ptr)
+{
+#if defined(__i386__)
+ int val;
+ asm volatile ("movzwl %1, %0\n"
+ "xchgb %b0, %h0\n"
+ : "=q" (val)
+ : "m" (*(uint16_t *)ptr));
+ return (int16_t)val;
+#else
+ uint8_t *b = (uint8_t *) ptr;
+ return (int16_t)((b[0] << 8) | b[1]);
+#endif
+}
+
+static inline int ldl_raw(void *ptr)
+{
+#if defined(__i386__) || defined(__x86_64__)
+ int val;
+ asm volatile ("movl %1, %0\n"
+ "bswap %0\n"
+ : "=r" (val)
+ : "m" (*(uint32_t *)ptr));
+ return val;
+#else
+ uint8_t *b = (uint8_t *) ptr;
+ return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
+#endif
+}
+
+static inline uint64_t ldq_raw(void *ptr)
+{
+ uint32_t a,b;
+ a = ldl_raw(ptr);
+ b = ldl_raw(ptr+4);
+ return (((uint64_t)a<<32)|b);
+}
+
+static inline void stw_raw(void *ptr, int v)
+{
+#if defined(__i386__)
+ asm volatile ("xchgb %b0, %h0\n"
+ "movw %w0, %1\n"
+ : "=q" (v)
+ : "m" (*(uint16_t *)ptr), "0" (v));
+#else
+ uint8_t *d = (uint8_t *) ptr;
+ d[0] = v >> 8;
+ d[1] = v;
+#endif
+}
+
+static inline void stl_raw(void *ptr, int v)
+{
+#if defined(__i386__) || defined(__x86_64__)
+ asm volatile ("bswap %0\n"
+ "movl %0, %1\n"
+ : "=r" (v)
+ : "m" (*(uint32_t *)ptr), "0" (v));
+#else
+ uint8_t *d = (uint8_t *) ptr;
+ d[0] = v >> 24;
+ d[1] = v >> 16;
+ d[2] = v >> 8;
+ d[3] = v;
+#endif
+}
+
+static inline void stq_raw(void *ptr, uint64_t v)
+{
+ stl_raw(ptr, v >> 32);
+ stl_raw(ptr + 4, v);
+}
+
+/* float access */
+
+static inline float ldfl_raw(void *ptr)
+{
+ union {
+ float f;
+ uint32_t i;
+ } u;
+ u.i = ldl_raw(ptr);
+ return u.f;
+}
+
+static inline void stfl_raw(void *ptr, float v)
+{
+ union {
+ float f;
+ uint32_t i;
+ } u;
+ u.f = v;
+ stl_raw(ptr, u.i);
+}
+
+static inline double ldfq_raw(void *ptr)
+{
+ CPU_DoubleU u;
+ u.l.upper = ldl_raw(ptr);
+ u.l.lower = ldl_raw(ptr + 4);
+ return u.d;
+}
+
+static inline void stfq_raw(void *ptr, double v)
+{
+ CPU_DoubleU u;
+ u.d = v;
+ stl_raw(ptr, u.l.upper);
+ stl_raw(ptr + 4, u.l.lower);
+}
+
+#else
+
+static inline int lduw_raw(void *ptr)
+{
+ return *(uint16_t *)ptr;
+}
+
+static inline int ldsw_raw(void *ptr)
+{
+ return *(int16_t *)ptr;
+}
+
+static inline int ldl_raw(void *ptr)
+{
+ return *(uint32_t *)ptr;
+}
+
+static inline uint64_t ldq_raw(void *ptr)
+{
+ return *(uint64_t *)ptr;
+}
+
+static inline void stw_raw(void *ptr, int v)
+{
+ *(uint16_t *)ptr = v;
+}
+
+static inline void stl_raw(void *ptr, int v)
+{
+ *(uint32_t *)ptr = v;
+}
+
+static inline void stq_raw(void *ptr, uint64_t v)
+{
+ *(uint64_t *)ptr = v;
+}
+
+/* float access */
+
+static inline float ldfl_raw(void *ptr)
+{
+ return *(float *)ptr;
+}
+
+static inline double ldfq_raw(void *ptr)
+{
+ return *(double *)ptr;
+}
+
+static inline void stfl_raw(void *ptr, float v)
+{
+ *(float *)ptr = v;
+}
+
+static inline void stfq_raw(void *ptr, double v)
+{
+ *(double *)ptr = v;
+}
+#endif
+
+/* MMU memory access macros */
+
+#if defined(CONFIG_USER_ONLY)
+
+/* if user mode, no other memory access functions */
+#define ldub(p) ldub_raw(p)
+#define ldsb(p) ldsb_raw(p)
+#define lduw(p) lduw_raw(p)
+#define ldsw(p) ldsw_raw(p)
+#define ldl(p) ldl_raw(p)
+#define ldq(p) ldq_raw(p)
+#define ldfl(p) ldfl_raw(p)
+#define ldfq(p) ldfq_raw(p)
+#define stb(p, v) stb_raw(p, v)
+#define stw(p, v) stw_raw(p, v)
+#define stl(p, v) stl_raw(p, v)
+#define stq(p, v) stq_raw(p, v)
+#define stfl(p, v) stfl_raw(p, v)
+#define stfq(p, v) stfq_raw(p, v)
+
+#define ldub_code(p) ldub_raw(p)
+#define ldsb_code(p) ldsb_raw(p)
+#define lduw_code(p) lduw_raw(p)
+#define ldsw_code(p) ldsw_raw(p)
+#define ldl_code(p) ldl_raw(p)
+
+#define ldub_kernel(p) ldub_raw(p)
+#define ldsb_kernel(p) ldsb_raw(p)
+#define lduw_kernel(p) lduw_raw(p)
+#define ldsw_kernel(p) ldsw_raw(p)
+#define ldl_kernel(p) ldl_raw(p)
+#define ldfl_kernel(p) ldfl_raw(p)
+#define ldfq_kernel(p) ldfq_raw(p)
+#define stb_kernel(p, v) stb_raw(p, v)
+#define stw_kernel(p, v) stw_raw(p, v)
+#define stl_kernel(p, v) stl_raw(p, v)
+#define stq_kernel(p, v) stq_raw(p, v)
+#define stfl_kernel(p, v) stfl_raw(p, v)
+#define stfq_kernel(p, vt) stfq_raw(p, v)
+
+#endif /* defined(CONFIG_USER_ONLY) */
+
+/* page related stuff */
+
+#define TARGET_PAGE_SIZE (1 << TARGET_PAGE_BITS)
+#define TARGET_PAGE_MASK ~(TARGET_PAGE_SIZE - 1)
+#define TARGET_PAGE_ALIGN(addr) (((addr) + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK)
+
+extern unsigned long qemu_real_host_page_size;
+extern unsigned long qemu_host_page_bits;
+extern unsigned long qemu_host_page_size;
+extern unsigned long qemu_host_page_mask;
+
+#define HOST_PAGE_ALIGN(addr) (((addr) + qemu_host_page_size - 1) & qemu_host_page_mask)
+
+/* same as PROT_xxx */
+#define PAGE_READ 0x0001
+#define PAGE_WRITE 0x0002
+#define PAGE_EXEC 0x0004
+#define PAGE_BITS (PAGE_READ | PAGE_WRITE | PAGE_EXEC)
+#define PAGE_VALID 0x0008
+/* original state of the write flag (used when tracking self-modifying
+ code */
+#define PAGE_WRITE_ORG 0x0010
+
+void page_dump(FILE *f);
+int page_get_flags(unsigned long address);
+void page_set_flags(unsigned long start, unsigned long end, int flags);
+void page_unprotect_range(uint8_t *data, unsigned long data_size);
+
+#define CPUState CPUX86State
+
+void cpu_dump_state(CPUState *env, FILE *f,
+ int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
+ int flags);
+
+void cpu_abort(CPUState *env, const char *fmt, ...);
+extern CPUState *cpu_single_env;
+extern int code_copy_enabled;
+
+#define CPU_INTERRUPT_EXIT 0x01 /* wants exit from main loop */
+#define CPU_INTERRUPT_HARD 0x02 /* hardware interrupt pending */
+#define CPU_INTERRUPT_EXITTB 0x04 /* exit the current TB (use for x86 a20 case) */
+#define CPU_INTERRUPT_TIMER 0x08 /* internal timer exception pending */
+void cpu_interrupt(CPUState *s, int mask);
+void cpu_reset_interrupt(CPUState *env, int mask);
+
+int cpu_breakpoint_insert(CPUState *env, target_ulong pc);
+int cpu_breakpoint_remove(CPUState *env, target_ulong pc);
+void cpu_single_step(CPUState *env, int enabled);
+void cpu_reset(CPUState *s);
+CPUState *cpu_init(void);
+int main_loop(void);
+
+/* Return the physical page corresponding to a virtual one. Use it
+ only for debugging because no protection checks are done. Return -1
+ if no page found. */
+target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr);
+
+#define CPU_LOG_TB_OUT_ASM (1 << 0)
+#define CPU_LOG_TB_IN_ASM (1 << 1)
+#define CPU_LOG_TB_OP (1 << 2)
+#define CPU_LOG_TB_OP_OPT (1 << 3)
+#define CPU_LOG_INT (1 << 4)
+#define CPU_LOG_EXEC (1 << 5)
+#define CPU_LOG_PCALL (1 << 6)
+#define CPU_LOG_IOPORT (1 << 7)
+#define CPU_LOG_TB_CPU (1 << 8)
+
+/* define log items */
+typedef struct CPULogItem {
+ int mask;
+ const char *name;
+ const char *help;
+} CPULogItem;
+
+extern CPULogItem cpu_log_items[];
+
+void cpu_set_log(int log_flags);
+void cpu_set_log_filename(const char *filename);
+int cpu_str_to_log_mask(const char *str);
+
+/* IO ports API */
+
+/* NOTE: as these functions may be even used when there is an isa
+ brige on non x86 targets, we always defined them */
+#ifndef NO_CPU_IO_DEFS
+void cpu_outb(CPUState *env, int addr, int val);
+void cpu_outw(CPUState *env, int addr, int val);
+void cpu_outl(CPUState *env, int addr, int val);
+int cpu_inb(CPUState *env, int addr);
+int cpu_inw(CPUState *env, int addr);
+int cpu_inl(CPUState *env, int addr);
+#endif
+
+/* memory API */
+
+extern int phys_ram_size;
+extern int phys_ram_fd;
+extern uint8_t *phys_ram_base;
+extern uint8_t *phys_ram_dirty;
+
+/* physical memory access */
+#define IO_MEM_NB_ENTRIES 256
+#define TLB_INVALID_MASK (1 << 3)
+#define IO_MEM_SHIFT 4
+
+#define IO_MEM_RAM (0 << IO_MEM_SHIFT) /* hardcoded offset */
+#define IO_MEM_ROM (1 << IO_MEM_SHIFT) /* hardcoded offset */
+#define IO_MEM_UNASSIGNED (2 << IO_MEM_SHIFT)
+#define IO_MEM_CODE (3 << IO_MEM_SHIFT) /* used internally, never use directly */
+#define IO_MEM_NOTDIRTY (4 << IO_MEM_SHIFT) /* used internally, never use directly */
+
+typedef void CPUWriteMemoryFunc(void *opaque, target_phys_addr_t addr, uint32_t value);
+typedef uint32_t CPUReadMemoryFunc(void *opaque, target_phys_addr_t addr);
+
+void cpu_register_physical_memory(target_phys_addr_t start_addr,
+ unsigned long size,
+ unsigned long phys_offset);
+int cpu_register_io_memory(int io_index,
+ CPUReadMemoryFunc **mem_read,
+ CPUWriteMemoryFunc **mem_write,
+ void *opaque);
+CPUWriteMemoryFunc **cpu_get_io_memory_write(int io_index);
+CPUReadMemoryFunc **cpu_get_io_memory_read(int io_index);
+
+void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
+ int len, int is_write);
+static inline void cpu_physical_memory_read(target_phys_addr_t addr,
+ uint8_t *buf, int len)
+{
+ cpu_physical_memory_rw(addr, buf, len, 0);
+}
+static inline void cpu_physical_memory_write(target_phys_addr_t addr,
+ const uint8_t *buf, int len)
+{
+ cpu_physical_memory_rw(addr, (uint8_t *)buf, len, 1);
+}
+
+int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
+ uint8_t *buf, int len, int is_write);
+
+/* read dirty bit (return 0 or 1) */
+static inline int cpu_physical_memory_is_dirty(target_ulong addr)
+{
+ return phys_ram_dirty[addr >> TARGET_PAGE_BITS];
+}
+
+static inline void cpu_physical_memory_set_dirty(target_ulong addr)
+{
+ phys_ram_dirty[addr >> TARGET_PAGE_BITS] = 1;
+}
+
+void cpu_physical_memory_reset_dirty(target_ulong start, target_ulong end);
+
+#endif /* CPU_ALL_H */
--- /dev/null
+/*
+ * common defines for all CPUs
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef CPU_DEFS_H
+#define CPU_DEFS_H
+
+#include "config.h"
+#include <setjmp.h>
+#include <inttypes.h>
+#include "osdep.h"
+
+#ifndef TARGET_LONG_BITS
+#error TARGET_LONG_BITS must be defined before including this header
+#endif
+
+#if defined(__alpha__) || defined (__ia64__) || defined(__x86_64__)
+#define HOST_LONG_BITS 64
+#else
+#define HOST_LONG_BITS 32
+#endif
+
+#ifndef TARGET_PHYS_ADDR_BITS
+#if TARGET_LONG_BITS >= HOST_LONG_BITS
+#define TARGET_PHYS_ADDR_BITS TARGET_LONG_BITS
+#else
+#define TARGET_PHYS_ADDR_BITS HOST_LONG_BITS
+#endif
+#endif
+
+#define TARGET_LONG_SIZE (TARGET_LONG_BITS / 8)
+
+/* target_ulong is the type of a virtual address */
+#if TARGET_LONG_SIZE == 4
+typedef int32_t target_long;
+typedef uint32_t target_ulong;
+#elif TARGET_LONG_SIZE == 8
+typedef int64_t target_long;
+typedef uint64_t target_ulong;
+#else
+#error TARGET_LONG_SIZE undefined
+#endif
+
+/* target_phys_addr_t is the type of a physical address (its size can
+ be different from 'target_ulong'). We have sizeof(target_phys_addr)
+ = max(sizeof(unsigned long),
+ sizeof(size_of_target_physical_address)) because we must pass a
+ host pointer to memory operations in some cases */
+
+#if TARGET_PHYS_ADDR_BITS == 32
+typedef uint32_t target_phys_addr_t;
+#elif TARGET_PHYS_ADDR_BITS == 64
+typedef uint64_t target_phys_addr_t;
+#else
+#error TARGET_PHYS_ADDR_BITS undefined
+#endif
+
+#define HOST_LONG_SIZE (HOST_LONG_BITS / 8)
+
+#define EXCP_INTERRUPT 256 /* async interruption */
+#define EXCP_HLT 257 /* hlt instruction reached */
+#define EXCP_DEBUG 258 /* cpu stopped after a breakpoint or singlestep */
+
+#define MAX_BREAKPOINTS 32
+
+#define CPU_TLB_SIZE 256
+
+typedef struct CPUTLBEntry {
+ /* bit 31 to TARGET_PAGE_BITS : virtual address
+ bit TARGET_PAGE_BITS-1..IO_MEM_SHIFT : if non zero, memory io
+ zone number
+ bit 3 : indicates that the entry is invalid
+ bit 2..0 : zero
+ */
+ target_ulong address;
+ /* addend to virtual address to get physical address */
+ target_phys_addr_t addend;
+} CPUTLBEntry;
+
+#endif
--- /dev/null
+/*
+ * i386 virtual CPU header
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef CPU_I386_H
+#define CPU_I386_H
+
+#include "config.h"
+
+#ifdef TARGET_X86_64
+#define TARGET_LONG_BITS 64
+#else
+#define TARGET_LONG_BITS 32
+#endif
+
+/* target supports implicit self modifying code */
+#define TARGET_HAS_SMC
+/* support for self modifying code even if the modified instruction is
+ close to the modifying instruction */
+#define TARGET_HAS_PRECISE_SMC
+
+#include "cpu-defs.h"
+
+#if defined(__i386__) && !defined(CONFIG_SOFTMMU)
+#define USE_CODE_COPY
+#endif
+
+/* Empty for now */
+typedef struct CPUX86State {
+ uint32_t a20_mask;
+ int interrupt_request;
+ int send_event;
+} CPUX86State;
+
+#ifndef IN_OP_I386
+void cpu_x86_outb(CPUX86State *env, int addr, int val);
+void cpu_x86_outw(CPUX86State *env, int addr, int val);
+void cpu_x86_outl(CPUX86State *env, int addr, int val);
+int cpu_x86_inb(CPUX86State *env, int addr);
+int cpu_x86_inw(CPUX86State *env, int addr);
+int cpu_x86_inl(CPUX86State *env, int addr);
+#endif
+
+CPUX86State *cpu_x86_init(void);
+int cpu_x86_exec(CPUX86State *s);
+void cpu_x86_close(CPUX86State *s);
+int cpu_get_pic_interrupt(CPUX86State *s);
+/* MSDOS compatibility mode FPU exception support */
+void cpu_set_ferr(CPUX86State *s);
+
+#define TARGET_PAGE_BITS 12
+#include "cpu-all.h"
+
+#endif /* CPU_I386_H */
--- /dev/null
+#!/bin/sh
+
+# QEMU keysym adapter: create a header file to link the name to its keysym
+#
+# Copyright (c) 2004,2005 Johannes E. Schindelin
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
+
+type="$1"
+cflags="$2"
+if [ -z "$cflags" ]; then
+ echo "Usage: $0 vnc|sdl cflags"
+ exit 1
+fi
+
+
+case "$type" in
+vnc)
+ ignore_case=''
+ header=rfb/keysym.h
+ keysym_t=rfbKeySym
+ pattern='^#define[ ]*XK_\([^ ]*\)[ ].*$'
+ replacement='#ifdef XK_\1\n{\"\1\", XK_\1},\n#endif'
+ extra_replace='cat'
+ extra_sort='cat'
+ ;;
+sdl)
+ ignore_case='-f'
+ header=SDL_keysym.h
+ keysym_t=int
+ pattern='^[ ]*SDLK_\([^ ]*\)[ ]*=.*$'
+ replacement='{\"\1\", SDLK_\1},'
+ extra_replace='sed -e s/{"\([RL]\)\(SUPER\|META\|ALT\|CONTROL\|SHIFT\)/{"\2_\1/ -e s/{"\([RL]\)CTRL/{"CONTROL_\1/ -e s/{"\(PAGE\)\(UP\|DOWN\)/{"\1_\2/ -e s/{"\(KP\)\([0-9]\)/{"\1_\2/ -e s/{"KP_MINUS/{"KP_SUBTRACT/ -e s/{"KP_PLUS/{"KP_ADD/ -e s/{"KP_PERIOD/{"KP_DECIMAL/ -e s/{"\(LEFT\|RIGHT\)\(PAREN\|BRACKET\)/{"\2\1/ -e s/{"EXCLAIM/{"EXCLAM/ -e s/{"\(CAPS\|NUM\)\(LOCK\)/{"\1_\2/ -e s/{"SCROLLOCK/{"SCROLL_LOCK/ -e s/{"KP_EQUALS/{"KP_EQUAL/ -e s/{"SYSREQ/{"SYS_REQ/ -e s/{"QUOTE"/{"APOSTROPHE"/ -e s/{"BACKQUOTE/{"GRAVE/ -e s/{"EQUALS/{"EQUAL/ -e s/{"EURO/{"EUROSIGN/ -e s/{"COMPOSE/{"MULTI_KEY/ -e s/{"MODE/{"MODE_SWITCH/ -e s/{"HASH/{"NUMBERSIGN/ -e s/{"WORLD_68/{"ADIAERESIS/ -e s/{"WORLD_86/{"ODIAERESIS/ -e s/{"WORLD_92/{"UDIAERESIS/ -e s/{"WORLD_63/{"SSHARP/ -e s/{"WORLD_20/{"ACUTE/ -e s/{"CARET/{"ASCIICIRCUM/'
+ extra_sort='sort -f'
+ ;;
+*) echo "Unknown type: $type is neither vnc nor sdl"; exit 1;;
+esac
+
+outfile=keysym_adapter_"$type".h
+
+echo "typedef struct {" > $outfile
+echo " const char* name;" >> $outfile
+echo " $keysym_t keysym;" >> $outfile
+echo "} name2keysym_t;" >> $outfile
+echo "static name2keysym_t name2keysym[]={" >> $outfile
+
+for path in $(echo "$cflags" | sed "s/-I/ /g"); do
+ if [ -f $path/$header ]; then
+ cat $path/$header
+ fi
+done | tr "\011" " " | LC_ALL=C sort $ignore_case | uniq | \
+sed -n -e "s/$pattern/$replacement/p" | $extra_replace | \
+LC_ALL=C $extra_sort >> $outfile
+
+echo "{0,0}};" >> $outfile
+
+if [ -n "$ignore_case" ]; then
+echo "#define KEYBOARD_IGNORE_CASE" >> $outfile
+fi
+
+
--- /dev/null
+/*
+ * internal execution defines for qemu
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/* allow to see translation results - the slowdown should be negligible, so we leave it */
+#define DEBUG_DISAS
+
+#ifndef glue
+#define xglue(x, y) x ## y
+#define glue(x, y) xglue(x, y)
+#define stringify(s) tostring(s)
+#define tostring(s) #s
+#endif
+
+#if GCC_MAJOR < 3
+#define __builtin_expect(x, n) (x)
+#endif
+
+#ifdef __i386__
+#define REGPARM(n) __attribute((regparm(n)))
+#else
+#define REGPARM(n)
+#endif
+
+/* is_jmp field values */
+#define DISAS_NEXT 0 /* next instruction can be analyzed */
+#define DISAS_JUMP 1 /* only pc was modified dynamically */
+#define DISAS_UPDATE 2 /* cpu state was modified dynamically */
+#define DISAS_TB_JUMP 3 /* only pc was modified statically */
+
+struct TranslationBlock;
+
+/* XXX: make safe guess about sizes */
+#define MAX_OP_PER_INSTR 32
+#define OPC_BUF_SIZE 512
+#define OPC_MAX_SIZE (OPC_BUF_SIZE - MAX_OP_PER_INSTR)
+
+#define OPPARAM_BUF_SIZE (OPC_BUF_SIZE * 3)
+
+extern uint16_t gen_opc_buf[OPC_BUF_SIZE];
+extern uint32_t gen_opparam_buf[OPPARAM_BUF_SIZE];
+extern uint32_t gen_opc_pc[OPC_BUF_SIZE];
+extern uint32_t gen_opc_npc[OPC_BUF_SIZE];
+extern uint8_t gen_opc_cc_op[OPC_BUF_SIZE];
+extern uint8_t gen_opc_instr_start[OPC_BUF_SIZE];
+
+typedef void (GenOpFunc)(void);
+typedef void (GenOpFunc1)(long);
+typedef void (GenOpFunc2)(long, long);
+typedef void (GenOpFunc3)(long, long, long);
+
+#if defined(TARGET_I386)
+
+void optimize_flags_init(void);
+
+#endif
+
+extern FILE *logfile;
+extern int loglevel;
+
+int gen_intermediate_code(CPUState *env, struct TranslationBlock *tb);
+int gen_intermediate_code_pc(CPUState *env, struct TranslationBlock *tb);
+void dump_ops(const uint16_t *opc_buf, const uint32_t *opparam_buf);
+int cpu_gen_code(CPUState *env, struct TranslationBlock *tb,
+ int max_code_size, int *gen_code_size_ptr);
+int cpu_restore_state(struct TranslationBlock *tb,
+ CPUState *env, unsigned long searched_pc,
+ void *puc);
+int cpu_gen_code_copy(CPUState *env, struct TranslationBlock *tb,
+ int max_code_size, int *gen_code_size_ptr);
+int cpu_restore_state_copy(struct TranslationBlock *tb,
+ CPUState *env, unsigned long searched_pc,
+ void *puc);
+void cpu_resume_from_signal(CPUState *env1, void *puc);
+void cpu_exec_init(void);
+int page_unprotect(unsigned long address, unsigned long pc, void *puc);
+void tb_invalidate_phys_page_range(target_ulong start, target_ulong end,
+ int is_cpu_write_access);
+void tb_invalidate_page_range(target_ulong start, target_ulong end);
+void tlb_flush_page(CPUState *env, target_ulong addr);
+void tlb_flush(CPUState *env, int flush_global);
+int tlb_set_page(CPUState *env, target_ulong vaddr,
+ target_phys_addr_t paddr, int prot,
+ int is_user, int is_softmmu);
+
+#define CODE_GEN_MAX_SIZE 65536
+#define CODE_GEN_ALIGN 16 /* must be >= of the size of a icache line */
+
+#define CODE_GEN_HASH_BITS 15
+#define CODE_GEN_HASH_SIZE (1 << CODE_GEN_HASH_BITS)
+
+#define CODE_GEN_PHYS_HASH_BITS 15
+#define CODE_GEN_PHYS_HASH_SIZE (1 << CODE_GEN_PHYS_HASH_BITS)
+
+/* maximum total translate dcode allocated */
+
+/* NOTE: the translated code area cannot be too big because on some
+ archs the range of "fast" function calls is limited. Here is a
+ summary of the ranges:
+
+ i386 : signed 32 bits
+ arm : signed 26 bits
+ ppc : signed 24 bits
+ sparc : signed 32 bits
+ alpha : signed 23 bits
+*/
+
+#if defined(__alpha__)
+#define CODE_GEN_BUFFER_SIZE (2 * 1024 * 1024)
+#elif defined(__powerpc__)
+#define CODE_GEN_BUFFER_SIZE (6 * 1024 * 1024)
+#else
+#define CODE_GEN_BUFFER_SIZE (8 * 1024 * 1024)
+#endif
+
+//#define CODE_GEN_BUFFER_SIZE (128 * 1024)
+
+/* estimated block size for TB allocation */
+/* XXX: use a per code average code fragment size and modulate it
+ according to the host CPU */
+#if defined(CONFIG_SOFTMMU)
+#define CODE_GEN_AVG_BLOCK_SIZE 128
+#else
+#define CODE_GEN_AVG_BLOCK_SIZE 64
+#endif
+
+#define CODE_GEN_MAX_BLOCKS (CODE_GEN_BUFFER_SIZE / CODE_GEN_AVG_BLOCK_SIZE)
+
+#if defined(__powerpc__)
+#define USE_DIRECT_JUMP
+#endif
+#if defined(__i386__) && !defined(_WIN32)
+#define USE_DIRECT_JUMP
+#endif
+
+typedef struct TranslationBlock {
+ target_ulong pc; /* simulated PC corresponding to this block (EIP + CS base) */
+ target_ulong cs_base; /* CS base for this block */
+ unsigned int flags; /* flags defining in which context the code was generated */
+ uint16_t size; /* size of target code for this block (1 <=
+ size <= TARGET_PAGE_SIZE) */
+ uint16_t cflags; /* compile flags */
+#define CF_CODE_COPY 0x0001 /* block was generated in code copy mode */
+#define CF_TB_FP_USED 0x0002 /* fp ops are used in the TB */
+#define CF_FP_USED 0x0004 /* fp ops are used in the TB or in a chained TB */
+#define CF_SINGLE_INSN 0x0008 /* compile only a single instruction */
+
+ uint8_t *tc_ptr; /* pointer to the translated code */
+ struct TranslationBlock *hash_next; /* next matching tb for virtual address */
+ /* next matching tb for physical address. */
+ struct TranslationBlock *phys_hash_next;
+ /* first and second physical page containing code. The lower bit
+ of the pointer tells the index in page_next[] */
+ struct TranslationBlock *page_next[2];
+ target_ulong page_addr[2];
+
+ /* the following data are used to directly call another TB from
+ the code of this one. */
+ uint16_t tb_next_offset[2]; /* offset of original jump target */
+#ifdef USE_DIRECT_JUMP
+ uint16_t tb_jmp_offset[4]; /* offset of jump instruction */
+#else
+ uint32_t tb_next[2]; /* address of jump generated code */
+#endif
+ /* list of TBs jumping to this one. This is a circular list using
+ the two least significant bits of the pointers to tell what is
+ the next pointer: 0 = jmp_next[0], 1 = jmp_next[1], 2 =
+ jmp_first */
+ struct TranslationBlock *jmp_next[2];
+ struct TranslationBlock *jmp_first;
+} TranslationBlock;
+
+static inline unsigned int tb_hash_func(unsigned long pc)
+{
+ return pc & (CODE_GEN_HASH_SIZE - 1);
+}
+
+static inline unsigned int tb_phys_hash_func(unsigned long pc)
+{
+ return pc & (CODE_GEN_PHYS_HASH_SIZE - 1);
+}
+
+TranslationBlock *tb_alloc(unsigned long pc);
+void tb_flush(CPUState *env);
+void tb_link(TranslationBlock *tb);
+void tb_link_phys(TranslationBlock *tb,
+ target_ulong phys_pc, target_ulong phys_page2);
+
+extern TranslationBlock *tb_hash[CODE_GEN_HASH_SIZE];
+extern TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
+
+extern uint8_t code_gen_buffer[CODE_GEN_BUFFER_SIZE];
+extern uint8_t *code_gen_ptr;
+
+/* find a translation block in the translation cache. If not found,
+ return NULL and the pointer to the last element of the list in pptb */
+static inline TranslationBlock *tb_find(TranslationBlock ***pptb,
+ target_ulong pc,
+ target_ulong cs_base,
+ unsigned int flags)
+{
+ TranslationBlock **ptb, *tb;
+ unsigned int h;
+
+ h = tb_hash_func(pc);
+ ptb = &tb_hash[h];
+ for(;;) {
+ tb = *ptb;
+ if (!tb)
+ break;
+ if (tb->pc == pc && tb->cs_base == cs_base && tb->flags == flags)
+ return tb;
+ ptb = &tb->hash_next;
+ }
+ *pptb = ptb;
+ return NULL;
+}
+
+
+#if defined(USE_DIRECT_JUMP)
+
+#if defined(__powerpc__)
+static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr)
+{
+ uint32_t val, *ptr;
+
+ /* patch the branch destination */
+ ptr = (uint32_t *)jmp_addr;
+ val = *ptr;
+ val = (val & ~0x03fffffc) | ((addr - jmp_addr) & 0x03fffffc);
+ *ptr = val;
+ /* flush icache */
+ asm volatile ("dcbst 0,%0" : : "r"(ptr) : "memory");
+ asm volatile ("sync" : : : "memory");
+ asm volatile ("icbi 0,%0" : : "r"(ptr) : "memory");
+ asm volatile ("sync" : : : "memory");
+ asm volatile ("isync" : : : "memory");
+}
+#elif defined(__i386__)
+static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr)
+{
+ /* patch the branch destination */
+ *(uint32_t *)jmp_addr = addr - (jmp_addr + 4);
+ /* no need to flush icache explicitely */
+}
+#endif
+
+static inline void tb_set_jmp_target(TranslationBlock *tb,
+ int n, unsigned long addr)
+{
+ unsigned long offset;
+
+ offset = tb->tb_jmp_offset[n];
+ tb_set_jmp_target1((unsigned long)(tb->tc_ptr + offset), addr);
+ offset = tb->tb_jmp_offset[n + 2];
+ if (offset != 0xffff)
+ tb_set_jmp_target1((unsigned long)(tb->tc_ptr + offset), addr);
+}
+
+#else
+
+/* set the jump target */
+static inline void tb_set_jmp_target(TranslationBlock *tb,
+ int n, unsigned long addr)
+{
+ tb->tb_next[n] = addr;
+}
+
+#endif
+
+static inline void tb_add_jump(TranslationBlock *tb, int n,
+ TranslationBlock *tb_next)
+{
+ /* NOTE: this test is only needed for thread safety */
+ if (!tb->jmp_next[n]) {
+ /* patch the native jump address */
+ tb_set_jmp_target(tb, n, (unsigned long)tb_next->tc_ptr);
+
+ /* add in TB jmp circular list */
+ tb->jmp_next[n] = tb_next->jmp_first;
+ tb_next->jmp_first = (TranslationBlock *)((long)(tb) | (n));
+ }
+}
+
+TranslationBlock *tb_find_pc(unsigned long pc_ptr);
+
+#ifndef offsetof
+#define offsetof(type, field) ((size_t) &((type *)0)->field)
+#endif
+
+#if defined(_WIN32)
+#define ASM_DATA_SECTION ".section \".data\"\n"
+#define ASM_PREVIOUS_SECTION ".section .text\n"
+#elif defined(__APPLE__)
+#define ASM_DATA_SECTION ".data\n"
+#define ASM_PREVIOUS_SECTION ".text\n"
+#define ASM_NAME(x) "_" #x
+#else
+#define ASM_DATA_SECTION ".section \".data\"\n"
+#define ASM_PREVIOUS_SECTION ".previous\n"
+#define ASM_NAME(x) stringify(x)
+#endif
+
+#if defined(__powerpc__)
+
+/* we patch the jump instruction directly */
+#define JUMP_TB(opname, tbparam, n, eip)\
+do {\
+ asm volatile (ASM_DATA_SECTION\
+ ASM_NAME(__op_label) #n "." ASM_NAME(opname) ":\n"\
+ ".long 1f\n"\
+ ASM_PREVIOUS_SECTION \
+ "b " ASM_NAME(__op_jmp) #n "\n"\
+ "1:\n");\
+ T0 = (long)(tbparam) + (n);\
+ EIP = eip;\
+ EXIT_TB();\
+} while (0)
+
+#define JUMP_TB2(opname, tbparam, n)\
+do {\
+ asm volatile ("b " ASM_NAME(__op_jmp) #n "\n");\
+} while (0)
+
+#elif defined(__i386__) && defined(USE_DIRECT_JUMP)
+
+/* we patch the jump instruction directly */
+#define JUMP_TB(opname, tbparam, n, eip)\
+do {\
+ asm volatile (".section .data\n"\
+ ASM_NAME(__op_label) #n "." ASM_NAME(opname) ":\n"\
+ ".long 1f\n"\
+ ASM_PREVIOUS_SECTION \
+ "jmp " ASM_NAME(__op_jmp) #n "\n"\
+ "1:\n");\
+ T0 = (long)(tbparam) + (n);\
+ EIP = eip;\
+ EXIT_TB();\
+} while (0)
+
+#define JUMP_TB2(opname, tbparam, n)\
+do {\
+ asm volatile ("jmp " ASM_NAME(__op_jmp) #n "\n");\
+} while (0)
+
+#else
+
+/* jump to next block operations (more portable code, does not need
+ cache flushing, but slower because of indirect jump) */
+#define JUMP_TB(opname, tbparam, n, eip)\
+do {\
+ static void __attribute__((unused)) *__op_label ## n = &&label ## n;\
+ static void __attribute__((unused)) *dummy ## n = &&dummy_label ## n;\
+ goto *(void *)(((TranslationBlock *)tbparam)->tb_next[n]);\
+label ## n:\
+ T0 = (long)(tbparam) + (n);\
+ EIP = eip;\
+dummy_label ## n:\
+ EXIT_TB();\
+} while (0)
+
+/* second jump to same destination 'n' */
+#define JUMP_TB2(opname, tbparam, n)\
+do {\
+ goto *(void *)(((TranslationBlock *)tbparam)->tb_next[n - 2]);\
+} while (0)
+
+#endif
+
+extern CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
+extern CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
+extern void *io_mem_opaque[IO_MEM_NB_ENTRIES];
+
+#ifdef __powerpc__
+static inline int testandset (int *p)
+{
+ int ret;
+ __asm__ __volatile__ (
+ "0: lwarx %0,0,%1\n"
+ " xor. %0,%3,%0\n"
+ " bne 1f\n"
+ " stwcx. %2,0,%1\n"
+ " bne- 0b\n"
+ "1: "
+ : "=&r" (ret)
+ : "r" (p), "r" (1), "r" (0)
+ : "cr0", "memory");
+ return ret;
+}
+#endif
+
+#ifdef __i386__
+static inline int testandset (int *p)
+{
+ char ret;
+ long int readval;
+
+ __asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0"
+ : "=q" (ret), "=m" (*p), "=a" (readval)
+ : "r" (1), "m" (*p), "a" (0)
+ : "memory");
+ return ret;
+}
+#endif
+
+#ifdef __x86_64__
+static inline int testandset (int *p)
+{
+ char ret;
+ int readval;
+
+ __asm__ __volatile__ ("lock; cmpxchgl %3, %1; sete %0"
+ : "=q" (ret), "=m" (*p), "=a" (readval)
+ : "r" (1), "m" (*p), "a" (0)
+ : "memory");
+ return ret;
+}
+#endif
+
+#ifdef __s390__
+static inline int testandset (int *p)
+{
+ int ret;
+
+ __asm__ __volatile__ ("0: cs %0,%1,0(%2)\n"
+ " jl 0b"
+ : "=&d" (ret)
+ : "r" (1), "a" (p), "0" (*p)
+ : "cc", "memory" );
+ return ret;
+}
+#endif
+
+#ifdef __alpha__
+static inline int testandset (int *p)
+{
+ int ret;
+ unsigned long one;
+
+ __asm__ __volatile__ ("0: mov 1,%2\n"
+ " ldl_l %0,%1\n"
+ " stl_c %2,%1\n"
+ " beq %2,1f\n"
+ ".subsection 2\n"
+ "1: br 0b\n"
+ ".previous"
+ : "=r" (ret), "=m" (*p), "=r" (one)
+ : "m" (*p));
+ return ret;
+}
+#endif
+
+#ifdef __sparc__
+static inline int testandset (int *p)
+{
+ int ret;
+
+ __asm__ __volatile__("ldstub [%1], %0"
+ : "=r" (ret)
+ : "r" (p)
+ : "memory");
+
+ return (ret ? 1 : 0);
+}
+#endif
+
+#ifdef __arm__
+static inline int testandset (int *spinlock)
+{
+ register unsigned int ret;
+ __asm__ __volatile__("swp %0, %1, [%2]"
+ : "=r"(ret)
+ : "0"(1), "r"(spinlock));
+
+ return ret;
+}
+#endif
+
+#ifdef __mc68000
+static inline int testandset (int *p)
+{
+ char ret;
+ __asm__ __volatile__("tas %1; sne %0"
+ : "=r" (ret)
+ : "m" (p)
+ : "cc","memory");
+ return ret == 0;
+}
+#endif
+
+typedef int spinlock_t;
+
+#define SPIN_LOCK_UNLOCKED 0
+
+#if defined(CONFIG_USER_ONLY)
+static inline void spin_lock(spinlock_t *lock)
+{
+ while (testandset(lock));
+}
+
+static inline void spin_unlock(spinlock_t *lock)
+{
+ *lock = 0;
+}
+
+static inline int spin_trylock(spinlock_t *lock)
+{
+ return !testandset(lock);
+}
+#else
+static inline void spin_lock(spinlock_t *lock)
+{
+}
+
+static inline void spin_unlock(spinlock_t *lock)
+{
+}
+
+static inline int spin_trylock(spinlock_t *lock)
+{
+ return 1;
+}
+#endif
+
+extern spinlock_t tb_lock;
+
+extern int tb_invalidated_flag;
+
+#if !defined(CONFIG_USER_ONLY)
+
+void tlb_fill(unsigned long addr, int is_write, int is_user,
+ void *retaddr);
+
+#define ACCESS_TYPE 3
+#define MEMSUFFIX _code
+#define env cpu_single_env
+
+#undef ACCESS_TYPE
+#undef MEMSUFFIX
+#undef env
+
+#endif
+
+#if defined(CONFIG_USER_ONLY)
+static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr)
+{
+ return addr;
+}
+#else
+/* NOTE: this function can trigger an exception */
+/* NOTE2: the returned address is not exactly the physical address: it
+ is the offset relative to phys_ram_base */
+/* XXX: i386 target specific */
+static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr)
+{
+ return addr;
+}
+#endif
+
+//#define DEBUG_UNUSED_IOPORT
+//#define DEBUG_IOPORT
+#define TARGET_VMX
+
--- /dev/null
+/*
+ * virtual page mapping and translated block handling
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include "config.h"
+#ifdef _WIN32
+#include <windows.h>
+#else
+#include <sys/types.h>
+#include <sys/mman.h>
+#endif
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <inttypes.h>
+
+#include "cpu.h"
+#include "exec-all.h"
+
+//#define DEBUG_TB_INVALIDATE
+//#define DEBUG_FLUSH
+//#define DEBUG_TLB
+
+/* make various TB consistency checks */
+//#define DEBUG_TB_CHECK
+//#define DEBUG_TLB_CHECK
+
+/* threshold to flush the translated code buffer */
+#define CODE_GEN_BUFFER_MAX_SIZE (CODE_GEN_BUFFER_SIZE - CODE_GEN_MAX_SIZE)
+
+#define SMC_BITMAP_USE_THRESHOLD 10
+
+#define MMAP_AREA_START 0x00000000
+#define MMAP_AREA_END 0xa8000000
+
+TranslationBlock tbs[CODE_GEN_MAX_BLOCKS];
+TranslationBlock *tb_hash[CODE_GEN_HASH_SIZE];
+TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
+int nb_tbs;
+/* any access to the tbs or the page table must use this lock */
+spinlock_t tb_lock = SPIN_LOCK_UNLOCKED;
+
+uint8_t code_gen_buffer[CODE_GEN_BUFFER_SIZE];
+uint8_t *code_gen_ptr;
+
+int phys_ram_size;
+int phys_ram_fd;
+uint8_t *phys_ram_base;
+uint8_t *phys_ram_dirty;
+
+typedef struct PageDesc {
+ /* list of TBs intersecting this ram page */
+ TranslationBlock *first_tb;
+ /* in order to optimize self modifying code, we count the number
+ of lookups we do to a given page to use a bitmap */
+ unsigned int code_write_count;
+ uint8_t *code_bitmap;
+#if defined(CONFIG_USER_ONLY)
+ unsigned long flags;
+#endif
+} PageDesc;
+
+typedef struct PhysPageDesc {
+ /* offset in host memory of the page + io_index in the low 12 bits */
+ unsigned long phys_offset;
+} PhysPageDesc;
+
+typedef struct VirtPageDesc {
+ /* physical address of code page. It is valid only if 'valid_tag'
+ matches 'virt_valid_tag' */
+ target_ulong phys_addr;
+ unsigned int valid_tag;
+#if !defined(CONFIG_SOFTMMU)
+ /* original page access rights. It is valid only if 'valid_tag'
+ matches 'virt_valid_tag' */
+ unsigned int prot;
+#endif
+} VirtPageDesc;
+
+#define L2_BITS 10
+#define L1_BITS (32 - L2_BITS - TARGET_PAGE_BITS)
+
+#define L1_SIZE (1 << L1_BITS)
+#define L2_SIZE (1 << L2_BITS)
+
+unsigned long qemu_real_host_page_size;
+unsigned long qemu_host_page_bits;
+unsigned long qemu_host_page_size;
+unsigned long qemu_host_page_mask;
+
+/* io memory support */
+CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
+CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
+void *io_mem_opaque[IO_MEM_NB_ENTRIES];
+static int io_mem_nb = 1;
+
+/* log support */
+char *logfilename = "/tmp/qemu.log";
+FILE *logfile;
+int loglevel;
+
+void cpu_exec_init(void)
+{
+ /* alloc dirty bits array */
+ phys_ram_dirty = qemu_malloc(phys_ram_size >> TARGET_PAGE_BITS);
+}
+
+/* enable or disable low levels log */
+void cpu_set_log(int log_flags)
+{
+ loglevel = log_flags;
+ if (loglevel && !logfile) {
+ logfile = fopen(logfilename, "w");
+ if (!logfile) {
+ perror(logfilename);
+ _exit(1);
+ }
+#if !defined(CONFIG_SOFTMMU)
+ /* must avoid mmap() usage of glibc by setting a buffer "by hand" */
+ {
+ static uint8_t logfile_buf[4096];
+ setvbuf(logfile, logfile_buf, _IOLBF, sizeof(logfile_buf));
+ }
+#else
+ setvbuf(logfile, NULL, _IOLBF, 0);
+#endif
+ }
+}
+
+void cpu_set_log_filename(const char *filename)
+{
+ logfilename = strdup(filename);
+}
+
+/* mask must never be zero, except for A20 change call */
+void cpu_interrupt(CPUState *env, int mask)
+{
+ env->interrupt_request |= mask;
+}
+
+void cpu_reset_interrupt(CPUState *env, int mask)
+{
+ env->interrupt_request &= ~mask;
+}
+
+CPULogItem cpu_log_items[] = {
+ { CPU_LOG_TB_OUT_ASM, "out_asm",
+ "show generated host assembly code for each compiled TB" },
+ { CPU_LOG_TB_IN_ASM, "in_asm",
+ "show target assembly code for each compiled TB" },
+ { CPU_LOG_TB_OP, "op",
+ "show micro ops for each compiled TB (only usable if 'in_asm' used)" },
+#ifdef TARGET_I386
+ { CPU_LOG_TB_OP_OPT, "op_opt",
+ "show micro ops after optimization for each compiled TB" },
+#endif
+ { CPU_LOG_INT, "int",
+ "show interrupts/exceptions in short format" },
+ { CPU_LOG_EXEC, "exec",
+ "show trace before each executed TB (lots of logs)" },
+ { CPU_LOG_TB_CPU, "cpu",
+ "show CPU state before bloc translation" },
+#ifdef TARGET_I386
+ { CPU_LOG_PCALL, "pcall",
+ "show protected mode far calls/returns/exceptions" },
+#endif
+#ifdef DEBUG_IOPORT
+ { CPU_LOG_IOPORT, "ioport",
+ "show all i/o ports accesses" },
+#endif
+ { 0, NULL, NULL },
+};
+
+static int cmp1(const char *s1, int n, const char *s2)
+{
+ if (strlen(s2) != n)
+ return 0;
+ return memcmp(s1, s2, n) == 0;
+}
+
+/* takes a comma separated list of log masks. Return 0 if error. */
+int cpu_str_to_log_mask(const char *str)
+{
+ CPULogItem *item;
+ int mask;
+ const char *p, *p1;
+
+ p = str;
+ mask = 0;
+ for(;;) {
+ p1 = strchr(p, ',');
+ if (!p1)
+ p1 = p + strlen(p);
+ if(cmp1(p,p1-p,"all")) {
+ for(item = cpu_log_items; item->mask != 0; item++) {
+ mask |= item->mask;
+ }
+ } else {
+ for(item = cpu_log_items; item->mask != 0; item++) {
+ if (cmp1(p, p1 - p, item->name))
+ goto found;
+ }
+ return 0;
+ }
+ found:
+ mask |= item->mask;
+ if (*p1 != ',')
+ break;
+ p = p1 + 1;
+ }
+ return mask;
+}
+
+void cpu_abort(CPUState *env, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ fprintf(stderr, "qemu: fatal: ");
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, "\n");
+ va_end(ap);
+ abort();
+}
+
+
+/* XXX: Simple implementation. Fix later */
+#define MAX_MMIO 32
+struct mmio_space {
+ target_phys_addr_t start;
+ unsigned long size;
+ unsigned long io_index;
+} mmio[MAX_MMIO];
+unsigned long mmio_cnt;
+
+/* register physical memory. 'size' must be a multiple of the target
+ page size. If (phys_offset & ~TARGET_PAGE_MASK) != 0, then it is an
+ io memory page */
+void cpu_register_physical_memory(target_phys_addr_t start_addr,
+ unsigned long size,
+ unsigned long phys_offset)
+{
+ if (mmio_cnt == MAX_MMIO) {
+ fprintf(logfile, "too many mmio regions\n");
+ exit(-1);
+ }
+ mmio[mmio_cnt].io_index = phys_offset;
+ mmio[mmio_cnt].start = start_addr;
+ mmio[mmio_cnt++].size = size;
+}
+
+/* mem_read and mem_write are arrays of functions containing the
+ function to access byte (index 0), word (index 1) and dword (index
+ 2). All functions must be supplied. If io_index is non zero, the
+ corresponding io zone is modified. If it is zero, a new io zone is
+ allocated. The return value can be used with
+ cpu_register_physical_memory(). (-1) is returned if error. */
+int cpu_register_io_memory(int io_index,
+ CPUReadMemoryFunc **mem_read,
+ CPUWriteMemoryFunc **mem_write,
+ void *opaque)
+{
+ int i;
+
+ if (io_index <= 0) {
+ if (io_index >= IO_MEM_NB_ENTRIES)
+ return -1;
+ io_index = io_mem_nb++;
+ } else {
+ if (io_index >= IO_MEM_NB_ENTRIES)
+ return -1;
+ }
+
+ for(i = 0;i < 3; i++) {
+ io_mem_read[io_index][i] = mem_read[i];
+ io_mem_write[io_index][i] = mem_write[i];
+ }
+ io_mem_opaque[io_index] = opaque;
+ return io_index << IO_MEM_SHIFT;
+}
+
+CPUWriteMemoryFunc **cpu_get_io_memory_write(int io_index)
+{
+ return io_mem_write[io_index >> IO_MEM_SHIFT];
+}
+
+CPUReadMemoryFunc **cpu_get_io_memory_read(int io_index)
+{
+ return io_mem_read[io_index >> IO_MEM_SHIFT];
+}
+
+/* physical memory access (slow version, mainly for debug) */
+#if defined(CONFIG_USER_ONLY)
+void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
+ int len, int is_write)
+{
+ int l, flags;
+ target_ulong page;
+
+ while (len > 0) {
+ page = addr & TARGET_PAGE_MASK;
+ l = (page + TARGET_PAGE_SIZE) - addr;
+ if (l > len)
+ l = len;
+ flags = page_get_flags(page);
+ if (!(flags & PAGE_VALID))
+ return;
+ if (is_write) {
+ if (!(flags & PAGE_WRITE))
+ return;
+ memcpy((uint8_t *)addr, buf, len);
+ } else {
+ if (!(flags & PAGE_READ))
+ return;
+ memcpy(buf, (uint8_t *)addr, len);
+ }
+ len -= l;
+ buf += l;
+ addr += l;
+ }
+}
+#else
+
+int iomem_index(target_phys_addr_t addr)
+{
+ int i;
+
+ for (i = 0; i < mmio_cnt; i++) {
+ unsigned long start, end;
+
+ start = mmio[i].start;
+ end = mmio[i].start + mmio[i].size;
+
+ if ((addr >= start) && (addr <= end)){
+ return (mmio[i].io_index >> IO_MEM_SHIFT) & (IO_MEM_NB_ENTRIES - 1);
+ }
+ }
+ return 0;
+}
+
+void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
+ int len, int is_write)
+{
+ int l, io_index;
+ uint8_t *ptr;
+ uint32_t val;
+ target_phys_addr_t page;
+ unsigned long pd;
+
+ while (len > 0) {
+ page = addr & TARGET_PAGE_MASK;
+ l = (page + TARGET_PAGE_SIZE) - addr;
+ if (l > len)
+ l = len;
+
+ pd = page;
+ io_index = iomem_index(page);
+ if (is_write) {
+ if (io_index) {
+ if (l >= 4 && ((addr & 3) == 0)) {
+ /* 32 bit read access */
+ val = ldl_raw(buf);
+ io_mem_write[io_index][2](io_mem_opaque[io_index], addr, val);
+ l = 4;
+ } else if (l >= 2 && ((addr & 1) == 0)) {
+ /* 16 bit read access */
+ val = lduw_raw(buf);
+ io_mem_write[io_index][1](io_mem_opaque[io_index], addr, val);
+ l = 2;
+ } else {
+ /* 8 bit access */
+ val = ldub_raw(buf);
+ io_mem_write[io_index][0](io_mem_opaque[io_index], addr, val);
+ l = 1;
+ }
+ } else {
+ unsigned long addr1;
+
+ addr1 = (pd & TARGET_PAGE_MASK) + (addr & ~TARGET_PAGE_MASK);
+ /* RAM case */
+ ptr = phys_ram_base + addr1;
+ memcpy(ptr, buf, l);
+ }
+ } else {
+ if (io_index) {
+ if (l >= 4 && ((addr & 3) == 0)) {
+ /* 32 bit read access */
+ val = io_mem_read[io_index][2](io_mem_opaque[io_index], addr);
+ stl_raw(buf, val);
+ l = 4;
+ } else if (l >= 2 && ((addr & 1) == 0)) {
+ /* 16 bit read access */
+ val = io_mem_read[io_index][1](io_mem_opaque[io_index], addr);
+ stw_raw(buf, val);
+ l = 2;
+ } else {
+ /* 8 bit access */
+ val = io_mem_read[io_index][0](io_mem_opaque[io_index], addr);
+ stb_raw(buf, val);
+ l = 1;
+ }
+ } else {
+ /* RAM case */
+ ptr = phys_ram_base + (pd & TARGET_PAGE_MASK) +
+ (addr & ~TARGET_PAGE_MASK);
+ memcpy(buf, ptr, l);
+ }
+ }
+ len -= l;
+ buf += l;
+ addr += l;
+ }
+}
+#endif
+
+/* virtual memory access for debug */
+int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
+ uint8_t *buf, int len, int is_write)
+{
+ int l;
+ target_ulong page, phys_addr;
+
+ while (len > 0) {
+ page = addr & TARGET_PAGE_MASK;
+ phys_addr = cpu_get_phys_page_debug(env, page);
+ /* if no physical page mapped, return an error */
+ if (phys_addr == -1)
+ return -1;
+ l = (page + TARGET_PAGE_SIZE) - addr;
+ if (l > len)
+ l = len;
+ cpu_physical_memory_rw(phys_addr + (addr & ~TARGET_PAGE_MASK),
+ buf, l, is_write);
+ len -= l;
+ buf += l;
+ addr += l;
+ }
+ return 0;
+}
+
+void cpu_physical_memory_reset_dirty(target_ulong start, target_ulong end)
+{
+}
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: vga.bitmap.h,v 1.4 2002/05/25 14:22:53 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-typedef struct {
- unsigned char data[16];
- } bx_fontcharbitmap_t;
-
-static const bx_fontcharbitmap_t bx_vgafont[256] = {
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0x81, 0xa5, 0x99, 0x81, 0x81, 0x7e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x7e, 0xff, 0xdb, 0xff, 0xff, 0xdb, 0xe7, 0xff, 0xff, 0x7e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x36, 0x7f, 0x7f, 0x7f, 0x7f, 0x3e, 0x1c, 0x08, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x08, 0x1c, 0x3e, 0x7f, 0x3e, 0x1c, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0xe7, 0xe7, 0xe7, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x18, 0x3c, 0x7e, 0xff, 0xff, 0x7e, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, 0xff, 0xff, 0xff, 0xff }},
-{{ 0x00, 0x00, 0x78, 0x60, 0x70, 0x58, 0x1e, 0x33, 0x33, 0x33, 0x33, 0x1e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x3c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0xfc, 0xcc, 0xfc, 0x0c, 0x0c, 0x0c, 0x0c, 0x0e, 0x0f, 0x07, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0xfe, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0xc6, 0xe6, 0xe7, 0x67, 0x03, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x18, 0x18, 0xdb, 0x3c, 0xe7, 0x3c, 0xdb, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x7f, 0x1f, 0x0f, 0x07, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x40, 0x60, 0x70, 0x78, 0x7c, 0x7f, 0x7c, 0x78, 0x70, 0x60, 0x40, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0xfe, 0xdb, 0xdb, 0xdb, 0xde, 0xd8, 0xd8, 0xd8, 0xd8, 0xd8, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x3e, 0x63, 0x06, 0x1c, 0x36, 0x63, 0x63, 0x36, 0x1c, 0x30, 0x63, 0x3e, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x18, 0x3c, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x30, 0x7f, 0x30, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x06, 0x7f, 0x06, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x03, 0x03, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x36, 0x7f, 0x36, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x08, 0x1c, 0x1c, 0x3e, 0x3e, 0x7f, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x7f, 0x7f, 0x3e, 0x3e, 0x1c, 0x1c, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x66, 0x66, 0x66, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x36, 0x36, 0x7f, 0x36, 0x36, 0x36, 0x7f, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x18, 0x18, 0x3e, 0x63, 0x43, 0x03, 0x3e, 0x60, 0x60, 0x61, 0x63, 0x3e, 0x18, 0x18, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x43, 0x63, 0x30, 0x18, 0x0c, 0x06, 0x63, 0x61, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x1c, 0x36, 0x36, 0x1c, 0x6e, 0x3b, 0x33, 0x33, 0x33, 0x6e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x0c, 0x0c, 0x0c, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x18, 0x30, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x0c, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x40, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x1c, 0x36, 0x63, 0x63, 0x6b, 0x6b, 0x63, 0x63, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x18, 0x1c, 0x1e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x3e, 0x63, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x03, 0x63, 0x7f, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x3e, 0x63, 0x60, 0x60, 0x3c, 0x60, 0x60, 0x60, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x30, 0x38, 0x3c, 0x36, 0x33, 0x7f, 0x30, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x7f, 0x03, 0x03, 0x03, 0x3f, 0x60, 0x60, 0x60, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x1c, 0x06, 0x03, 0x03, 0x3f, 0x63, 0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x7f, 0x63, 0x60, 0x60, 0x30, 0x18, 0x0c, 0x0c, 0x0c, 0x0c, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x7e, 0x60, 0x60, 0x60, 0x30, 0x1e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x18, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x06, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x3e, 0x63, 0x63, 0x30, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x3e, 0x63, 0x63, 0x7b, 0x7b, 0x7b, 0x3b, 0x03, 0x3e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x08, 0x1c, 0x36, 0x63, 0x63, 0x7f, 0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x3f, 0x66, 0x66, 0x66, 0x3e, 0x66, 0x66, 0x66, 0x66, 0x3f, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x3c, 0x66, 0x43, 0x03, 0x03, 0x03, 0x03, 0x43, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x1f, 0x36, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x36, 0x1f, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x7f, 0x66, 0x46, 0x16, 0x1e, 0x16, 0x06, 0x46, 0x66, 0x7f, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x7f, 0x66, 0x46, 0x16, 0x1e, 0x16, 0x06, 0x06, 0x06, 0x0f, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x3c, 0x66, 0x43, 0x03, 0x03, 0x7b, 0x63, 0x63, 0x66, 0x5c, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x7f, 0x63, 0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x78, 0x30, 0x30, 0x30, 0x30, 0x30, 0x33, 0x33, 0x33, 0x1e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x67, 0x66, 0x66, 0x36, 0x1e, 0x1e, 0x36, 0x66, 0x66, 0x67, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x0f, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x46, 0x66, 0x7f, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x63, 0x77, 0x7f, 0x7f, 0x6b, 0x63, 0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x63, 0x67, 0x6f, 0x7f, 0x7b, 0x73, 0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x3f, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x06, 0x06, 0x06, 0x0f, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x6b, 0x7b, 0x3e, 0x30, 0x70, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x3f, 0x66, 0x66, 0x66, 0x3e, 0x36, 0x66, 0x66, 0x66, 0x67, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x3e, 0x63, 0x63, 0x06, 0x1c, 0x30, 0x60, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x7e, 0x7e, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x36, 0x1c, 0x08, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x6b, 0x6b, 0x6b, 0x7f, 0x77, 0x36, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x63, 0x63, 0x36, 0x3e, 0x1c, 0x1c, 0x3e, 0x36, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x7f, 0x63, 0x61, 0x30, 0x18, 0x0c, 0x06, 0x43, 0x63, 0x7f, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x3c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x3c, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x01, 0x03, 0x07, 0x0e, 0x1c, 0x38, 0x70, 0x60, 0x40, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x3c, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x3c, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x08, 0x1c, 0x36, 0x63, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00 }},
-{{ 0x0c, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x30, 0x3e, 0x33, 0x33, 0x33, 0x6e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x07, 0x06, 0x06, 0x1e, 0x36, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x63, 0x03, 0x03, 0x03, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x38, 0x30, 0x30, 0x3c, 0x36, 0x33, 0x33, 0x33, 0x33, 0x6e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x63, 0x7f, 0x03, 0x03, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x1c, 0x36, 0x26, 0x06, 0x0f, 0x06, 0x06, 0x06, 0x06, 0x0f, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3e, 0x30, 0x33, 0x1e, 0x00 }},
-{{ 0x00, 0x00, 0x07, 0x06, 0x06, 0x36, 0x6e, 0x66, 0x66, 0x66, 0x66, 0x67, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x18, 0x18, 0x00, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x60, 0x60, 0x00, 0x70, 0x60, 0x60, 0x60, 0x60, 0x60, 0x60, 0x66, 0x66, 0x3c, 0x00 }},
-{{ 0x00, 0x00, 0x07, 0x06, 0x06, 0x66, 0x36, 0x1e, 0x1e, 0x36, 0x66, 0x67, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x37, 0x7f, 0x6b, 0x6b, 0x6b, 0x6b, 0x63, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x06, 0x0f, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x33, 0x33, 0x33, 0x33, 0x33, 0x3e, 0x30, 0x30, 0x78, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x6e, 0x66, 0x06, 0x06, 0x06, 0x0f, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x63, 0x06, 0x1c, 0x30, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x08, 0x0c, 0x0c, 0x3f, 0x0c, 0x0c, 0x0c, 0x0c, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x6e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x63, 0x6b, 0x6b, 0x6b, 0x7f, 0x36, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x36, 0x1c, 0x1c, 0x1c, 0x36, 0x63, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x7e, 0x60, 0x30, 0x1f, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x33, 0x18, 0x0c, 0x06, 0x63, 0x7f, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x70, 0x18, 0x18, 0x18, 0x0e, 0x18, 0x18, 0x18, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x0e, 0x18, 0x18, 0x18, 0x70, 0x18, 0x18, 0x18, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x6e, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x08, 0x1c, 0x36, 0x63, 0x63, 0x63, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x3c, 0x66, 0x43, 0x03, 0x03, 0x03, 0x43, 0x66, 0x3c, 0x30, 0x60, 0x3e, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x33, 0x00, 0x00, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x6e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x30, 0x18, 0x0c, 0x00, 0x3e, 0x63, 0x7f, 0x03, 0x03, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x08, 0x1c, 0x36, 0x00, 0x1e, 0x30, 0x3e, 0x33, 0x33, 0x33, 0x6e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x33, 0x00, 0x00, 0x1e, 0x30, 0x3e, 0x33, 0x33, 0x33, 0x6e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x06, 0x0c, 0x18, 0x00, 0x1e, 0x30, 0x3e, 0x33, 0x33, 0x33, 0x6e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x1c, 0x36, 0x1c, 0x00, 0x1e, 0x30, 0x3e, 0x33, 0x33, 0x33, 0x6e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x3c, 0x66, 0x06, 0x06, 0x66, 0x3c, 0x30, 0x60, 0x3c, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x08, 0x1c, 0x36, 0x00, 0x3e, 0x63, 0x7f, 0x03, 0x03, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x63, 0x00, 0x00, 0x3e, 0x63, 0x7f, 0x03, 0x03, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x06, 0x0c, 0x18, 0x00, 0x3e, 0x63, 0x7f, 0x03, 0x03, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x66, 0x00, 0x00, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x18, 0x3c, 0x66, 0x00, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x06, 0x0c, 0x18, 0x00, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x63, 0x00, 0x08, 0x1c, 0x36, 0x63, 0x63, 0x7f, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x1c, 0x36, 0x1c, 0x00, 0x1c, 0x36, 0x63, 0x63, 0x7f, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x18, 0x0c, 0x06, 0x00, 0x7f, 0x66, 0x06, 0x3e, 0x06, 0x06, 0x66, 0x7f, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x6e, 0x6c, 0x7e, 0x1b, 0x1b, 0x76, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x7c, 0x36, 0x33, 0x33, 0x7f, 0x33, 0x33, 0x33, 0x33, 0x73, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x08, 0x1c, 0x36, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x63, 0x00, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x06, 0x0c, 0x18, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x0c, 0x1e, 0x33, 0x00, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x6e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x06, 0x0c, 0x18, 0x00, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x6e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x63, 0x00, 0x00, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x7e, 0x60, 0x30, 0x1e, 0x00 }},
-{{ 0x00, 0x63, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x63, 0x00, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x18, 0x18, 0x3c, 0x66, 0x06, 0x06, 0x06, 0x66, 0x3c, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x1c, 0x36, 0x26, 0x06, 0x0f, 0x06, 0x06, 0x06, 0x06, 0x67, 0x3f, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x1f, 0x33, 0x33, 0x1f, 0x23, 0x33, 0x7b, 0x33, 0x33, 0x33, 0x63, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x70, 0xd8, 0x18, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1b, 0x0e, 0x00, 0x00 }},
-{{ 0x00, 0x18, 0x0c, 0x06, 0x00, 0x1e, 0x30, 0x3e, 0x33, 0x33, 0x33, 0x6e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x30, 0x18, 0x0c, 0x00, 0x1c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x18, 0x0c, 0x06, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x18, 0x0c, 0x06, 0x00, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33, 0x6e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x6e, 0x3b, 0x00, 0x3b, 0x66, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x6e, 0x3b, 0x00, 0x63, 0x67, 0x6f, 0x7f, 0x7b, 0x73, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x3c, 0x36, 0x36, 0x7c, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x1c, 0x36, 0x36, 0x1c, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x0c, 0x0c, 0x00, 0x0c, 0x0c, 0x06, 0x03, 0x63, 0x63, 0x3e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x60, 0x60, 0x60, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x03, 0x03, 0x43, 0x63, 0x33, 0x18, 0x0c, 0x06, 0x3b, 0x61, 0x30, 0x18, 0x7c, 0x00, 0x00 }},
-{{ 0x00, 0x03, 0x03, 0x43, 0x63, 0x33, 0x18, 0x0c, 0x66, 0x73, 0x79, 0x7c, 0x60, 0x60, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x3c, 0x3c, 0x3c, 0x18, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x36, 0x1b, 0x36, 0x6c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x1b, 0x36, 0x6c, 0x36, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22 }},
-{{ 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55 }},
-{{ 0xbb, 0xee, 0xbb, 0xee, 0xbb, 0xee, 0xbb, 0xee, 0xbb, 0xee, 0xbb, 0xee, 0xbb, 0xee, 0xbb, 0xee }},
-{{ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 }},
-{{ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 }},
-{{ 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 }},
-{{ 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6f, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 }},
-{{ 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6f, 0x60, 0x6f, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c }},
-{{ 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x60, 0x6f, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c }},
-{{ 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6f, 0x60, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 }},
-{{ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 }},
-{{ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 }},
-{{ 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 }},
-{{ 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0xec, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c }},
-{{ 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0xec, 0x0c, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0c, 0xec, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c }},
-{{ 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0xef, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xef, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c }},
-{{ 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0xec, 0x0c, 0xec, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0xef, 0x00, 0xef, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c }},
-{{ 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c }},
-{{ 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0xfc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c }},
-{{ 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0xff, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c, 0x6c }},
-{{ 0x18, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 }},
-{{ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 }},
-{{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }},
-{{ 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f }},
-{{ 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0 }},
-{{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x1b, 0x1b, 0x1b, 0x3b, 0x6e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x1e, 0x33, 0x33, 0x33, 0x1b, 0x33, 0x63, 0x63, 0x63, 0x33, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x7f, 0x63, 0x63, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x7f, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x7f, 0x63, 0x06, 0x0c, 0x18, 0x0c, 0x06, 0x63, 0x7f, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x1b, 0x1b, 0x1b, 0x1b, 0x1b, 0x0e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x3e, 0x06, 0x06, 0x03, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x7e, 0x18, 0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x1c, 0x36, 0x63, 0x63, 0x7f, 0x63, 0x63, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x1c, 0x36, 0x63, 0x63, 0x63, 0x36, 0x36, 0x36, 0x36, 0x77, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x78, 0x0c, 0x18, 0x30, 0x7c, 0x66, 0x66, 0x66, 0x66, 0x3c, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xdb, 0xdb, 0xdb, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0xc0, 0x60, 0x7e, 0xdb, 0xdb, 0xcf, 0x7e, 0x06, 0x03, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x38, 0x0c, 0x06, 0x06, 0x3e, 0x06, 0x06, 0x06, 0x0c, 0x38, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x3e, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x63, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x30, 0x18, 0x0c, 0x06, 0x0c, 0x18, 0x30, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x70, 0xd8, 0xd8, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18 }},
-{{ 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1b, 0x1b, 0x1b, 0x0e, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x6e, 0x3b, 0x00, 0x6e, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x1c, 0x36, 0x36, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0xf0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x37, 0x36, 0x36, 0x3c, 0x38, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x1b, 0x36, 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x0e, 0x1b, 0x0c, 0x06, 0x13, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-{{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }},
-};
+++ /dev/null
-TOPDIR= ..
-CXXFLAGS=-I. -I../include -I..
-OBJS= gui.o keymap.o siminterface.o textconfig.o x.o rfb.o term.o
-
-all: libgui.a
-
-libgui.a: $(OBJS)
- $(AR) $(ARFLAGS) $@ $(OBJS)
-
-include $(TOPDIR)/mk/helix.mk
-
-install:: all
+++ /dev/null
-# Copyright (C) 2002 MandrakeSoft S.A.
-#
-# MandrakeSoft S.A.
-# 43, rue d'Aboukir
-# 75002 Paris - France
-# http://www.linux-mandrake.com/
-# http://www.mandrakesoft.com/
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-# Makefile for the gui component of bochs
-
-
-@SUFFIX_LINE@
-
-prefix = @prefix@
-exec_prefix = @exec_prefix@
-srcdir = @srcdir@
-VPATH = @srcdir@
-bindir = @bindir@
-libdir = @libdir@
-mandir = @mandir@
-man1dir = $(mandir)/man1
-man5dir = $(mandir)/man5
-docdir = $(prefix)/share/doc/bochs
-sharedir = $(prefix)/share/bochs
-top_builddir = ..
-top_srcdir = @top_srcdir@
-
-SHELL = /bin/sh
-
-@SET_MAKE@
-
-CXX = @CXX@
-CXXFLAGS = $(BX_INCDIRS) @CXXFLAGS@ @GUI_CXXFLAGS@
-LOCAL_CXXFLAGS =
-LDFLAGS = @LDFLAGS@
-LIBS = @LIBS@
-X_CFLAGS = @X_CFLAGS@
-RANLIB = @RANLIB@
-PLUGIN_PATH=@libdir@
-top_builddir = ..
-LIBTOOL=@LIBTOOL@
-WIN32_DLL_IMPORT_LIBRARY=../dllexports.a
-BX_INCDIRS = -I.. -I$(srcdir)/.. -I../iodev -I$(srcdir)/../iodev -I../@INSTRUMENT_DIR@ -I$(srcdir)/../@INSTRUMENT_DIR@
-
-GUI_OBJS_X11 = x.o
-GUI_OBJS_SDL = sdl.o
-GUI_OBJS_SVGA = svga.o
-GUI_OBJS_BEOS = beos.o
-GUI_OBJS_WIN32 = win32.o
-GUI_OBJS_MACOS = macintosh.o
-GUI_OBJS_CARBON = carbon.o
-GUI_OBJS_NOGUI = nogui.o
-GUI_OBJS_TERM = term.o
-GUI_OBJS_RFB = rfb.o
-GUI_OBJS_AMIGAOS = amigaos.o
-GUI_OBJS_WX = wx.o
-GUI_OBJS_WX_SUPPORT = wxmain.o wxdialog.o
-OBJS_THAT_CANNOT_BE_PLUGINS = keymap.o gui.o siminterface.o textconfig.o @DIALOG_OBJS@
-OBJS_THAT_CAN_BE_PLUGINS = @GUI_OBJS@
-
-X_LIBS = @X_LIBS@
-X_PRE_LIBS = @X_PRE_LIBS@
-GUI_LINK_OPTS_X = $(X_LIBS) $(X_PRE_LIBS) -lX11 -lXpm
-GUI_LINK_OPTS_SDL = `sdl-config --cflags --libs`
-GUI_LINK_OPTS_SVGA = -lvga -lvgagl
-GUI_LINK_OPTS_BEOS = -lbe
-GUI_LINK_OPTS_RFB = @RFB_LIBS@
-GUI_LINK_OPTS_AMIGAOS =
-GUI_LINK_OPTS_WIN32 = -luser32 -lgdi32 -lcomdlg32 -lcomctl32
-GUI_LINK_OPTS_WIN32_VCPP = user32.lib gdi32.lib winmm.lib \
- comdlg32.lib comctl32.lib wsock32.lib
-GUI_LINK_OPTS_MACOS =
-GUI_LINK_OPTS_CARBON = -framework Carbon
-GUI_LINK_OPTS_NOGUI =
-GUI_LINK_OPTS_TERM = @GUI_LINK_OPTS_TERM@
-GUI_LINK_OPTS_WX = @GUI_LINK_OPTS_WX@
-GUI_LINK_OPTS = @GUI_LINK_OPTS@ @DEVICE_LINK_OPTS@
-
-NONPLUGIN_OBJS = @GUI_NON_PLUGIN_OBJS@
-PLUGIN_OBJS = @GUI_PLUGIN_OBJS@
-
-#
-# -------- end configurable options --------------------------
-#
-
-all: libgui.a
-
-plugins: $(PLUGIN_OBJS:@PLUGIN_LIBNAME_TRANSFORMATION@)
-
-libgui.a: $(NONPLUGIN_OBJS)
- @RMCOMMAND@ libgui.a
- @MAKELIB@ $(NONPLUGIN_OBJS)
- @RANLIB@ libgui.a
-
-# standard compile rule for C++ files
-.@CPP_SUFFIX@.o:
- $(CXX) @DASH@c $(CXXFLAGS) $(LOCAL_CXXFLAGS) @CXXFP@$< @OFP@$@
-
-##### building plugins with libtool
-%.lo: %.@CPP_SUFFIX@
- $(LIBTOOL) --mode=compile $(CXX) -c $(CXXFLAGS) $(LOCAL_CXXFLAGS) $< -o $@
-
-libbx_%.la: %.lo
- $(LIBTOOL) --mode=link $(CXX) -module $< -o $@ -rpath $(PLUGIN_PATH)
-
-libbx_x.la: x.lo
- $(LIBTOOL) --mode=link $(CXX) -module $< -o $@ -rpath $(PLUGIN_PATH) $(GUI_LINK_OPTS_X)
-
-libbx_sdl.la: sdl.lo
- $(LIBTOOL) --mode=link $(CXX) -module $< -o $@ -rpath $(PLUGIN_PATH) $(GUI_LINK_OPTS_SDL)
-
-libbx_svga.la: svga.lo
- $(LIBTOOL) --mode=link $(CXX) -module $< -o $@ -rpath $(PLUGIN_PATH) $(GUI_LINK_OPTS_SVGA)
-
-libbx_beos.la: beos.lo
- $(LIBTOOL) --mode=link $(CXX) -module $< -o $@ -rpath $(PLUGIN_PATH) $(GUI_LINK_OPTS_BEOS)
-
-libbx_rfb.la: rfb.lo
- $(LIBTOOL) --mode=link $(CXX) -module $< -o $@ -rpath $(PLUGIN_PATH) $(GUI_LINK_OPTS_RFB)
-
-libbx_amigaos.la: amigaos.lo
- $(LIBTOOL) --mode=link $(CXX) -module $< -o $@ -rpath $(PLUGIN_PATH) $(GUI_LINK_OPTS_AMIGAOS)
-
-libbx_win32.la: win32.lo
- $(LIBTOOL) --mode=link $(CXX) -module $< -o $@ -rpath $(PLUGIN_PATH) $(GUI_LINK_OPTS_WIN32)
-
-libbx_macos.la: macos.lo
- $(LIBTOOL) --mode=link $(CXX) -module $< -o $@ -rpath $(PLUGIN_PATH) $(GUI_LINK_OPTS_MACOS)
-
-libbx_carbon.la: carbon.lo
- $(LIBTOOL) --mode=link $(CXX) -module $< -o $@ -rpath $(PLUGIN_PATH) $(GUI_LINK_OPTS_CARBON)
-
-libbx_nogui.la: nogui.lo
- $(LIBTOOL) --mode=link $(CXX) -module $< -o $@ -rpath $(PLUGIN_PATH) $(GUI_LINK_OPTS_NOGUI)
-
-libbx_term.la: term.lo
- $(LIBTOOL) --mode=link $(CXX) -module $< -o $@ -rpath $(PLUGIN_PATH) $(GUI_LINK_OPTS_TERM)
-
-# special link rules for plugins that require more than one object file
-libbx_wx.la: $(GUI_OBJS_WX:.o=.lo) $(GUI_OBJS_WX_SUPPORT:.o=.lo)
- $(LIBTOOL) --mode=link $(CXX) -module $(GUI_OBJS_WX:.o=.lo) $(GUI_OBJS_WX_SUPPORT:.o=.lo) -o libbx_wx.la -rpath $(PLUGIN_PATH) $(GUI_LINK_OPTS_WX)
-
-#### building DLLs for win32 (tested on cygwin only)
-bx_%.dll: %.o
- $(CXX) $(CXXFLAGS) -shared -o $@ $< $(WIN32_DLL_IMPORT_LIBRARY) $(GUI_LINK_OPTS_WIN32)
-
-bx_wx.dll: $(GUI_OBJS_WX) $(GUI_OBJS_WX_SUPPORT)
- $(CXX) $(CXXFLAGS) -shared -o bx_wx.dll $(GUI_OBJS_WX) $(GUI_OBJS_WX_SUPPORT) $(WIN32_DLL_IMPORT_LIBRARY) `wx-config --libs` -luser32 -lgdi32 -lcomdlg32 -lcomctl32
-
-bx_sdl.dll: $(GUI_OBJS_SDL)
- $(CXX) $(CXXFLAGS) -shared -o bx_sdl.dll $(GUI_OBJS_SDL) $(WIN32_DLL_IMPORT_LIBRARY) $(GUI_LINK_OPTS_SDL)
-
-bx_rfb.dll: $(GUI_OBJS_RFB)
- $(CXX) $(CXXFLAGS) -shared -o bx_rfb.dll $(GUI_OBJS_RFB) $(WIN32_DLL_IMPORT_LIBRARY) $(GUI_LINK_OPTS_RFB)
-
-# no need to build DLLs for beos.o
-# no need to build DLLs for x.o
-
-##### end DLL section
-
-clean:
- @RMCOMMAND@ -rf .libs *.la *.a *.lo *.o *.dll
-
-dist-clean: clean
- @RMCOMMAND@ Makefile
-
-###########################################
-# all other dependencies generated by
-# gcc -MM -I.. -I../instrument/stubs `wx-config --cxxflags` *.cc |
-# sed -e 's/\.cc/.@CPP_SUFFIX@/g'
-# gcc -MM -I.. -I../instrument/stubs `wx-config --cxxflags` *.cc | \
-# sed -e 's/\.cc/.@CPP_SUFFIX@/g' -e 's/\.o:/.lo:/g'
-#
-# This means that every source file is listed twice, once with a .o rule
-# and then again with an identical .lo rule. The .lo rules are used when
-# building plugins.
-###########################################
-amigaos.o: amigaos.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \
- ../bx_debug/debug.h ../bxversion.h ../gui/siminterface.h ../state_file.h \
- ../cpu/cpu.h ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h \
- ../pc_system.h ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h \
- ../gui/textconfig.h ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h \
- ../iodev/biosdev.h ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h \
- ../iodev/harddrv.h ../iodev/cdrom.h ../iodev/keyboard.h \
- ../iodev/parallel.h ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h \
- ../iodev/pit82c54.h ../iodev/serial.h ../iodev/unmapped.h \
- ../iodev/eth.h ../iodev/ne2k.h ../iodev/guest2host.h \
- ../iodev/slowdown_timer.h ../instrument/stubs/instrument.h \
- icon_bochs.h amigagui.h
-beos.o: beos.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \
- ../bxversion.h ../gui/siminterface.h ../state_file.h ../cpu/cpu.h \
- ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h ../pc_system.h \
- ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \
- ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h ../iodev/biosdev.h \
- ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h ../iodev/harddrv.h \
- ../iodev/cdrom.h ../iodev/keyboard.h ../iodev/parallel.h \
- ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h ../iodev/pit82c54.h \
- ../iodev/serial.h ../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \
- ../iodev/guest2host.h ../iodev/slowdown_timer.h \
- ../instrument/stubs/instrument.h ../font/vga.bitmap.h
-carbon.o: carbon.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \
- ../bxversion.h ../gui/siminterface.h ../state_file.h ../cpu/cpu.h \
- ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h ../pc_system.h \
- ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \
- ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h ../iodev/biosdev.h \
- ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h ../iodev/harddrv.h \
- ../iodev/cdrom.h ../iodev/keyboard.h ../iodev/parallel.h \
- ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h ../iodev/pit82c54.h \
- ../iodev/serial.h ../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \
- ../iodev/guest2host.h ../iodev/slowdown_timer.h \
- ../instrument/stubs/instrument.h icon_bochs.h ../font/vga.bitmap.h
-gui.o: gui.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \
- ../bxversion.h ../gui/siminterface.h ../state_file.h ../cpu/cpu.h \
- ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h ../pc_system.h \
- ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \
- ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h ../iodev/biosdev.h \
- ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h ../iodev/harddrv.h \
- ../iodev/cdrom.h ../iodev/keyboard.h ../iodev/parallel.h \
- ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h ../iodev/pit82c54.h \
- ../iodev/serial.h ../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \
- ../iodev/guest2host.h ../iodev/slowdown_timer.h \
- ../instrument/stubs/instrument.h ../gui/bitmaps/floppya.h \
- ../gui/bitmaps/floppyb.h ../gui/bitmaps/mouse.h \
- ../gui/bitmaps/reset.h ../gui/bitmaps/power.h \
- ../gui/bitmaps/snapshot.h ../gui/bitmaps/copy.h \
- ../gui/bitmaps/paste.h ../gui/bitmaps/configbutton.h \
- ../gui/bitmaps/cdromd.h ../gui/bitmaps/userbutton.h
-keymap.o: keymap.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \
- ../bxversion.h ../gui/siminterface.h ../state_file.h ../cpu/cpu.h \
- ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h ../pc_system.h \
- ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \
- ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h ../iodev/biosdev.h \
- ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h ../iodev/harddrv.h \
- ../iodev/cdrom.h ../iodev/keyboard.h ../iodev/parallel.h \
- ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h ../iodev/pit82c54.h \
- ../iodev/serial.h ../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \
- ../iodev/guest2host.h ../iodev/slowdown_timer.h \
- ../instrument/stubs/instrument.h
-macintosh.o: macintosh.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \
- ../bx_debug/debug.h ../bxversion.h ../gui/siminterface.h ../state_file.h \
- ../cpu/cpu.h ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h \
- ../pc_system.h ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h \
- ../gui/textconfig.h ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h \
- ../iodev/biosdev.h ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h \
- ../iodev/harddrv.h ../iodev/cdrom.h ../iodev/keyboard.h \
- ../iodev/parallel.h ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h \
- ../iodev/pit82c54.h ../iodev/serial.h ../iodev/unmapped.h \
- ../iodev/eth.h ../iodev/ne2k.h ../iodev/guest2host.h \
- ../iodev/slowdown_timer.h ../instrument/stubs/instrument.h \
- icon_bochs.h ../font/vga.bitmap.h
-nogui.o: nogui.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \
- ../bxversion.h ../gui/siminterface.h ../state_file.h ../cpu/cpu.h \
- ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h ../pc_system.h \
- ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \
- ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h ../iodev/biosdev.h \
- ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h ../iodev/harddrv.h \
- ../iodev/cdrom.h ../iodev/keyboard.h ../iodev/parallel.h \
- ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h ../iodev/pit82c54.h \
- ../iodev/serial.h ../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \
- ../iodev/guest2host.h ../iodev/slowdown_timer.h \
- ../instrument/stubs/instrument.h icon_bochs.h
-rfb.o: rfb.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \
- ../bxversion.h ../gui/siminterface.h ../state_file.h ../cpu/cpu.h \
- ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h ../pc_system.h \
- ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \
- ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h ../iodev/biosdev.h \
- ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h ../iodev/harddrv.h \
- ../iodev/cdrom.h ../iodev/keyboard.h ../iodev/parallel.h \
- ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h ../iodev/pit82c54.h \
- ../iodev/serial.h ../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \
- ../iodev/guest2host.h ../iodev/slowdown_timer.h \
- ../instrument/stubs/instrument.h icon_bochs.h ../font/vga.bitmap.h \
- rfbproto.h
-sdl.o: sdl.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \
- ../bxversion.h ../gui/siminterface.h ../state_file.h ../cpu/cpu.h \
- ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h ../pc_system.h \
- ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \
- ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h ../iodev/biosdev.h \
- ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h ../iodev/harddrv.h \
- ../iodev/cdrom.h ../iodev/keyboard.h ../iodev/parallel.h \
- ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h ../iodev/pit82c54.h \
- ../iodev/serial.h ../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \
- ../iodev/guest2host.h ../iodev/slowdown_timer.h \
- ../instrument/stubs/instrument.h icon_bochs.h sdl.h sdlkeys.h
-siminterface.o: siminterface.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \
- ../bx_debug/debug.h ../bxversion.h ../gui/siminterface.h ../state_file.h \
- ../cpu/cpu.h ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h \
- ../pc_system.h ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h \
- ../gui/textconfig.h ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h \
- ../iodev/biosdev.h ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h \
- ../iodev/harddrv.h ../iodev/cdrom.h ../iodev/keyboard.h \
- ../iodev/parallel.h ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h \
- ../iodev/pit82c54.h ../iodev/serial.h ../iodev/unmapped.h \
- ../iodev/eth.h ../iodev/ne2k.h ../iodev/guest2host.h \
- ../iodev/slowdown_timer.h ../instrument/stubs/instrument.h
-svga.o: svga.@CPP_SUFFIX@ ../font/vga.bitmap.h ../bochs.h ../config.h ../osdep.h \
- ../bx_debug/debug.h ../bxversion.h ../gui/siminterface.h ../state_file.h \
- ../cpu/cpu.h ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h \
- ../pc_system.h ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h \
- ../gui/textconfig.h ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h \
- ../iodev/biosdev.h ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h \
- ../iodev/harddrv.h ../iodev/cdrom.h ../iodev/keyboard.h \
- ../iodev/parallel.h ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h \
- ../iodev/pit82c54.h ../iodev/serial.h ../iodev/unmapped.h \
- ../iodev/eth.h ../iodev/ne2k.h ../iodev/guest2host.h \
- ../iodev/slowdown_timer.h ../instrument/stubs/instrument.h \
- icon_bochs.h
-term.o: term.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \
- ../bxversion.h ../gui/siminterface.h ../state_file.h ../cpu/cpu.h \
- ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h ../pc_system.h \
- ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \
- ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h ../iodev/biosdev.h \
- ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h ../iodev/harddrv.h \
- ../iodev/cdrom.h ../iodev/keyboard.h ../iodev/parallel.h \
- ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h ../iodev/pit82c54.h \
- ../iodev/serial.h ../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \
- ../iodev/guest2host.h ../iodev/slowdown_timer.h \
- ../instrument/stubs/instrument.h icon_bochs.h
-textconfig.o: textconfig.@CPP_SUFFIX@ ../config.h ../osdep.h textconfig.h \
- siminterface.h ../extplugin.h ../ltdl.h
-win32.o: win32.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \
- ../bxversion.h ../gui/siminterface.h ../state_file.h ../cpu/cpu.h \
- ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h ../pc_system.h \
- ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \
- ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h ../iodev/biosdev.h \
- ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h ../iodev/harddrv.h \
- ../iodev/cdrom.h ../iodev/keyboard.h ../iodev/parallel.h \
- ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h ../iodev/pit82c54.h \
- ../iodev/serial.h ../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \
- ../iodev/guest2host.h ../iodev/slowdown_timer.h \
- ../instrument/stubs/instrument.h icon_bochs.h ../font/vga.bitmap.h
-wx.o: wx.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \
- ../bxversion.h ../gui/siminterface.h ../state_file.h ../cpu/cpu.h \
- ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h ../pc_system.h \
- ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \
- ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h ../iodev/biosdev.h \
- ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h ../iodev/harddrv.h \
- ../iodev/cdrom.h ../iodev/keyboard.h ../iodev/parallel.h \
- ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h ../iodev/pit82c54.h \
- ../iodev/serial.h ../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \
- ../iodev/guest2host.h ../iodev/slowdown_timer.h \
- ../instrument/stubs/instrument.h ../gui/icon_bochs.h \
- ../font/vga.bitmap.h wxmain.h
-wxdialog.o: wxdialog.@CPP_SUFFIX@ ../config.h ../osdep.h ../gui/siminterface.h \
- ../bxversion.h wxdialog.h wxmain.h
-wxmain.o: wxmain.@CPP_SUFFIX@ ../config.h ../osdep.h ../gui/siminterface.h \
- ../bxversion.h wxdialog.h wxmain.h ../extplugin.h ../ltdl.h \
- bitmaps/cdromd.xpm bitmaps/copy.xpm bitmaps/floppya.xpm \
- bitmaps/floppyb.xpm bitmaps/paste.xpm bitmaps/power.xpm \
- bitmaps/reset.xpm bitmaps/snapshot.xpm bitmaps/mouse.xpm \
- bitmaps/userbutton.xpm
-x.o: x.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \
- ../bxversion.h ../gui/siminterface.h ../state_file.h ../cpu/cpu.h \
- ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h ../pc_system.h \
- ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \
- ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h ../iodev/biosdev.h \
- ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h ../iodev/harddrv.h \
- ../iodev/cdrom.h ../iodev/keyboard.h ../iodev/parallel.h \
- ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h ../iodev/pit82c54.h \
- ../iodev/serial.h ../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \
- ../iodev/guest2host.h ../iodev/slowdown_timer.h \
- ../instrument/stubs/instrument.h icon_bochs.h
-amigaos.lo: amigaos.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \
- ../bx_debug/debug.h ../bxversion.h ../gui/siminterface.h ../state_file.h \
- ../cpu/cpu.h ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h \
- ../pc_system.h ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h \
- ../gui/textconfig.h ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h \
- ../iodev/biosdev.h ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h \
- ../iodev/harddrv.h ../iodev/cdrom.h ../iodev/keyboard.h \
- ../iodev/parallel.h ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h \
- ../iodev/pit82c54.h ../iodev/serial.h ../iodev/unmapped.h \
- ../iodev/eth.h ../iodev/ne2k.h ../iodev/guest2host.h \
- ../iodev/slowdown_timer.h ../instrument/stubs/instrument.h \
- icon_bochs.h amigagui.h
-beos.lo: beos.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \
- ../bxversion.h ../gui/siminterface.h ../state_file.h ../cpu/cpu.h \
- ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h ../pc_system.h \
- ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \
- ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h ../iodev/biosdev.h \
- ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h ../iodev/harddrv.h \
- ../iodev/cdrom.h ../iodev/keyboard.h ../iodev/parallel.h \
- ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h ../iodev/pit82c54.h \
- ../iodev/serial.h ../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \
- ../iodev/guest2host.h ../iodev/slowdown_timer.h \
- ../instrument/stubs/instrument.h ../font/vga.bitmap.h
-carbon.lo: carbon.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \
- ../bxversion.h ../gui/siminterface.h ../state_file.h ../cpu/cpu.h \
- ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h ../pc_system.h \
- ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \
- ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h ../iodev/biosdev.h \
- ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h ../iodev/harddrv.h \
- ../iodev/cdrom.h ../iodev/keyboard.h ../iodev/parallel.h \
- ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h ../iodev/pit82c54.h \
- ../iodev/serial.h ../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \
- ../iodev/guest2host.h ../iodev/slowdown_timer.h \
- ../instrument/stubs/instrument.h icon_bochs.h ../font/vga.bitmap.h
-gui.lo: gui.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \
- ../bxversion.h ../gui/siminterface.h ../state_file.h ../cpu/cpu.h \
- ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h ../pc_system.h \
- ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \
- ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h ../iodev/biosdev.h \
- ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h ../iodev/harddrv.h \
- ../iodev/cdrom.h ../iodev/keyboard.h ../iodev/parallel.h \
- ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h ../iodev/pit82c54.h \
- ../iodev/serial.h ../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \
- ../iodev/guest2host.h ../iodev/slowdown_timer.h \
- ../instrument/stubs/instrument.h ../gui/bitmaps/floppya.h \
- ../gui/bitmaps/floppyb.h ../gui/bitmaps/mouse.h \
- ../gui/bitmaps/reset.h ../gui/bitmaps/power.h \
- ../gui/bitmaps/snapshot.h ../gui/bitmaps/copy.h \
- ../gui/bitmaps/paste.h ../gui/bitmaps/configbutton.h \
- ../gui/bitmaps/cdromd.h ../gui/bitmaps/userbutton.h
-keymap.lo: keymap.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \
- ../bxversion.h ../gui/siminterface.h ../state_file.h ../cpu/cpu.h \
- ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h ../pc_system.h \
- ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \
- ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h ../iodev/biosdev.h \
- ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h ../iodev/harddrv.h \
- ../iodev/cdrom.h ../iodev/keyboard.h ../iodev/parallel.h \
- ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h ../iodev/pit82c54.h \
- ../iodev/serial.h ../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \
- ../iodev/guest2host.h ../iodev/slowdown_timer.h \
- ../instrument/stubs/instrument.h
-macintosh.lo: macintosh.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \
- ../bx_debug/debug.h ../bxversion.h ../gui/siminterface.h ../state_file.h \
- ../cpu/cpu.h ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h \
- ../pc_system.h ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h \
- ../gui/textconfig.h ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h \
- ../iodev/biosdev.h ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h \
- ../iodev/harddrv.h ../iodev/cdrom.h ../iodev/keyboard.h \
- ../iodev/parallel.h ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h \
- ../iodev/pit82c54.h ../iodev/serial.h ../iodev/unmapped.h \
- ../iodev/eth.h ../iodev/ne2k.h ../iodev/guest2host.h \
- ../iodev/slowdown_timer.h ../instrument/stubs/instrument.h \
- icon_bochs.h ../font/vga.bitmap.h
-nogui.lo: nogui.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \
- ../bxversion.h ../gui/siminterface.h ../state_file.h ../cpu/cpu.h \
- ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h ../pc_system.h \
- ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \
- ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h ../iodev/biosdev.h \
- ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h ../iodev/harddrv.h \
- ../iodev/cdrom.h ../iodev/keyboard.h ../iodev/parallel.h \
- ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h ../iodev/pit82c54.h \
- ../iodev/serial.h ../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \
- ../iodev/guest2host.h ../iodev/slowdown_timer.h \
- ../instrument/stubs/instrument.h icon_bochs.h
-rfb.lo: rfb.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \
- ../bxversion.h ../gui/siminterface.h ../state_file.h ../cpu/cpu.h \
- ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h ../pc_system.h \
- ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \
- ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h ../iodev/biosdev.h \
- ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h ../iodev/harddrv.h \
- ../iodev/cdrom.h ../iodev/keyboard.h ../iodev/parallel.h \
- ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h ../iodev/pit82c54.h \
- ../iodev/serial.h ../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \
- ../iodev/guest2host.h ../iodev/slowdown_timer.h \
- ../instrument/stubs/instrument.h icon_bochs.h ../font/vga.bitmap.h \
- rfbproto.h
-sdl.lo: sdl.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \
- ../bxversion.h ../gui/siminterface.h ../state_file.h ../cpu/cpu.h \
- ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h ../pc_system.h \
- ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \
- ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h ../iodev/biosdev.h \
- ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h ../iodev/harddrv.h \
- ../iodev/cdrom.h ../iodev/keyboard.h ../iodev/parallel.h \
- ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h ../iodev/pit82c54.h \
- ../iodev/serial.h ../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \
- ../iodev/guest2host.h ../iodev/slowdown_timer.h \
- ../instrument/stubs/instrument.h icon_bochs.h sdl.h sdlkeys.h
-siminterface.lo: siminterface.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h \
- ../bx_debug/debug.h ../bxversion.h ../gui/siminterface.h ../state_file.h \
- ../cpu/cpu.h ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h \
- ../pc_system.h ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h \
- ../gui/textconfig.h ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h \
- ../iodev/biosdev.h ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h \
- ../iodev/harddrv.h ../iodev/cdrom.h ../iodev/keyboard.h \
- ../iodev/parallel.h ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h \
- ../iodev/pit82c54.h ../iodev/serial.h ../iodev/unmapped.h \
- ../iodev/eth.h ../iodev/ne2k.h ../iodev/guest2host.h \
- ../iodev/slowdown_timer.h ../instrument/stubs/instrument.h
-svga.lo: svga.@CPP_SUFFIX@ ../font/vga.bitmap.h ../bochs.h ../config.h ../osdep.h \
- ../bx_debug/debug.h ../bxversion.h ../gui/siminterface.h ../state_file.h \
- ../cpu/cpu.h ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h \
- ../pc_system.h ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h \
- ../gui/textconfig.h ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h \
- ../iodev/biosdev.h ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h \
- ../iodev/harddrv.h ../iodev/cdrom.h ../iodev/keyboard.h \
- ../iodev/parallel.h ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h \
- ../iodev/pit82c54.h ../iodev/serial.h ../iodev/unmapped.h \
- ../iodev/eth.h ../iodev/ne2k.h ../iodev/guest2host.h \
- ../iodev/slowdown_timer.h ../instrument/stubs/instrument.h \
- icon_bochs.h
-term.lo: term.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \
- ../bxversion.h ../gui/siminterface.h ../state_file.h ../cpu/cpu.h \
- ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h ../pc_system.h \
- ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \
- ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h ../iodev/biosdev.h \
- ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h ../iodev/harddrv.h \
- ../iodev/cdrom.h ../iodev/keyboard.h ../iodev/parallel.h \
- ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h ../iodev/pit82c54.h \
- ../iodev/serial.h ../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \
- ../iodev/guest2host.h ../iodev/slowdown_timer.h \
- ../instrument/stubs/instrument.h icon_bochs.h
-textconfig.lo: textconfig.@CPP_SUFFIX@ ../config.h ../osdep.h textconfig.h \
- siminterface.h ../extplugin.h ../ltdl.h
-win32.lo: win32.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \
- ../bxversion.h ../gui/siminterface.h ../state_file.h ../cpu/cpu.h \
- ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h ../pc_system.h \
- ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \
- ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h ../iodev/biosdev.h \
- ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h ../iodev/harddrv.h \
- ../iodev/cdrom.h ../iodev/keyboard.h ../iodev/parallel.h \
- ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h ../iodev/pit82c54.h \
- ../iodev/serial.h ../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \
- ../iodev/guest2host.h ../iodev/slowdown_timer.h \
- ../instrument/stubs/instrument.h icon_bochs.h ../font/vga.bitmap.h
-wx.lo: wx.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \
- ../bxversion.h ../gui/siminterface.h ../state_file.h ../cpu/cpu.h \
- ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h ../pc_system.h \
- ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \
- ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h ../iodev/biosdev.h \
- ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h ../iodev/harddrv.h \
- ../iodev/cdrom.h ../iodev/keyboard.h ../iodev/parallel.h \
- ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h ../iodev/pit82c54.h \
- ../iodev/serial.h ../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \
- ../iodev/guest2host.h ../iodev/slowdown_timer.h \
- ../instrument/stubs/instrument.h ../gui/icon_bochs.h \
- ../font/vga.bitmap.h wxdialog.h wxmain.h
-wxdialog.lo: wxdialog.@CPP_SUFFIX@ ../config.h ../osdep.h ../gui/siminterface.h \
- ../bxversion.h wxdialog.h wxmain.h
-wxmain.lo: wxmain.@CPP_SUFFIX@ ../config.h ../osdep.h ../gui/siminterface.h \
- ../bxversion.h wxdialog.h wxmain.h ../extplugin.h ../ltdl.h \
- bitmaps/cdromd.xpm bitmaps/copy.xpm bitmaps/floppya.xpm \
- bitmaps/floppyb.xpm bitmaps/paste.xpm bitmaps/power.xpm \
- bitmaps/reset.xpm bitmaps/snapshot.xpm bitmaps/mouse.xpm \
- bitmaps/userbutton.xpm
-x.lo: x.@CPP_SUFFIX@ ../bochs.h ../config.h ../osdep.h ../bx_debug/debug.h \
- ../bxversion.h ../gui/siminterface.h ../state_file.h ../cpu/cpu.h \
- ../cpu/lazy_flags.h ../cpu/i387.h ../memory/memory.h ../pc_system.h \
- ../plugin.h ../extplugin.h ../ltdl.h ../gui/gui.h ../gui/textconfig.h \
- ../gui/keymap.h ../iodev/iodev.h ../iodev/vga.h ../iodev/biosdev.h \
- ../iodev/cmos.h ../iodev/dma.h ../iodev/floppy.h ../iodev/harddrv.h \
- ../iodev/cdrom.h ../iodev/keyboard.h ../iodev/parallel.h \
- ../iodev/pic.h ../iodev/pit.h ../iodev/pit_wrap.h ../iodev/pit82c54.h \
- ../iodev/serial.h ../iodev/unmapped.h ../iodev/eth.h ../iodev/ne2k.h \
- ../iodev/guest2host.h ../iodev/slowdown_timer.h \
- ../instrument/stubs/instrument.h icon_bochs.h
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: cdromd.h,v 1.1 2002/01/31 21:16:52 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-#define BX_CDROMD_BMAP_X 32
-#define BX_CDROMD_BMAP_Y 32
-
-static const unsigned char bx_cdromd_bmap[(BX_CONFIG_BMAP_X * BX_CONFIG_BMAP_Y)/8] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x0e, 0x00, 0x00, 0x10, 0x12, 0x00,
- 0x00, 0x10, 0x12, 0x00, 0x00, 0x10, 0x12, 0x00, 0x00, 0x60, 0x0e, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0x00, 0x0c, 0x30, 0x00,
- 0x00, 0xe2, 0x47, 0x00, 0x00, 0x19, 0x98, 0x00, 0x80, 0xe6, 0x67, 0x01,
- 0x40, 0x19, 0x98, 0x02, 0x20, 0xe5, 0xa7, 0x04, 0xa0, 0x12, 0x48, 0x05,
- 0x90, 0xca, 0x53, 0x09, 0x50, 0x25, 0xa4, 0x0a, 0x50, 0x15, 0xa8, 0x0a,
- 0x50, 0x15, 0xa8, 0x0a, 0x50, 0x15, 0xa8, 0x0a, 0x50, 0x15, 0xa8, 0x0a,
- 0x50, 0x25, 0xa4, 0x0a, 0x90, 0xca, 0x53, 0x09, 0xa0, 0x12, 0x48, 0x05,
- 0x20, 0xe5, 0xa7, 0x04, 0x40, 0x19, 0x98, 0x02, 0x80, 0xe6, 0x67, 0x01,
- 0x00, 0x19, 0x98, 0x00, 0x00, 0xe2, 0x47, 0x00, 0x00, 0x0c, 0x30, 0x00,
- 0x00, 0xf0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00
- };
-
-static const unsigned char bx_cdromd_eject_bmap[(BX_CONFIG_BMAP_X * BX_CONFIG_BMAP_Y)/8] = {
- 0x01, 0x00, 0x00, 0x80, 0x02, 0x60, 0x0e, 0x40, 0x04, 0x10, 0x12, 0x20,
- 0x08, 0x10, 0x12, 0x10, 0x10, 0x10, 0x12, 0x08, 0x20, 0x60, 0x0e, 0x04,
- 0x40, 0x00, 0x00, 0x02, 0x80, 0xf0, 0x0f, 0x01, 0x00, 0x0d, 0xb0, 0x00,
- 0x00, 0xe2, 0x47, 0x00, 0x00, 0x1d, 0xb8, 0x00, 0x80, 0xee, 0x77, 0x01,
- 0x40, 0x19, 0x98, 0x02, 0x20, 0xe5, 0xa7, 0x04, 0xa0, 0x52, 0x4a, 0x05,
- 0x90, 0xca, 0x53, 0x09, 0x50, 0xa5, 0xa5, 0x0a, 0x50, 0x55, 0xaa, 0x0a,
- 0x50, 0x35, 0xac, 0x0a, 0x50, 0x15, 0xa8, 0x0a, 0x50, 0x1d, 0xb8, 0x0a,
- 0x50, 0x25, 0xa4, 0x0a, 0x90, 0xca, 0x53, 0x09, 0xa0, 0x13, 0xc8, 0x05,
- 0xa0, 0xe5, 0xa7, 0x05, 0x40, 0x19, 0x98, 0x02, 0xa0, 0xe6, 0x67, 0x05,
- 0x10, 0x19, 0x98, 0x08, 0x08, 0xe2, 0x47, 0x10, 0x04, 0x0c, 0x30, 0x20,
- 0x02, 0xf0, 0x0f, 0x40, 0x01, 0x00, 0x00, 0x80
- };
+++ /dev/null
-/* XPM */
-static char *cdromd_xpm[] = {
-/* width height num_colors chars_per_pixel */
-" 32 32 2 1",
-/* colors */
-". c None",
-"# c #000000",
-/* pixels */
-"................................",
-".............##..###............",
-"............#....#..#...........",
-"............#....#..#...........",
-"............#....#..#...........",
-".............##..###............",
-"................................",
-"............########............",
-"..........##........##..........",
-".........#...######...#.........",
-"........#..##......##..#........",
-".......#.##..######..##.#.......",
-"......#.#..##......##..#.#......",
-".....#..#.#..######..#.#..#.....",
-".....#.#.#..#......#..#.#.#.....",
-"....#..#.#.#..####..#.#.#..#....",
-"....#.#.#.#..#....#..#.#.#.#....",
-"....#.#.#.#.#......#.#.#.#.#....",
-"....#.#.#.#.#......#.#.#.#.#....",
-"....#.#.#.#.#......#.#.#.#.#....",
-"....#.#.#.#.#......#.#.#.#.#....",
-"....#.#.#.#..#....#..#.#.#.#....",
-"....#..#.#.#..####..#.#.#..#....",
-".....#.#.#..#......#..#.#.#.....",
-".....#..#.#..######..#.#..#.....",
-"......#.#..##......##..#.#......",
-".......#.##..######..##.#.......",
-"........#..##......##..#........",
-".........#...######...#.........",
-"..........##........##..........",
-"............########............",
-"................................"
-};
+++ /dev/null
-#define BX_CONFIG_BMAP_X 32
-#define BX_CONFIG_BMAP_Y 32
-
-static const unsigned char bx_config_bmap[(BX_CONFIG_BMAP_X * BX_CONFIG_BMAP_Y)/8] = {
- 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x80, 0x01, 0xfc, 0x7f, 0xc0, 0x03,
- 0xfc, 0xff, 0xc1, 0x03, 0xfc, 0xff, 0xc1, 0x03, 0xfc, 0x7f, 0xc0, 0x03,
- 0x84, 0x07, 0xc0, 0x03, 0x80, 0x07, 0xc0, 0x03, 0x80, 0x07, 0xc0, 0x03,
- 0x80, 0x07, 0xc0, 0x03, 0x80, 0x07, 0xc0, 0x03, 0x80, 0x07, 0xc0, 0x03,
- 0x80, 0x07, 0xc0, 0x03, 0x80, 0x07, 0xc0, 0x03, 0x80, 0x07, 0xc0, 0x03,
- 0x80, 0x07, 0xc0, 0x03, 0x80, 0x07, 0xc0, 0x03, 0x80, 0x07, 0xc0, 0x03,
- 0x80, 0x07, 0xc0, 0x03, 0x80, 0x07, 0xe0, 0x07, 0x80, 0x07, 0xf0, 0x0f,
- 0x80, 0x07, 0x70, 0x0e, 0x80, 0x07, 0x30, 0x0c, 0x80, 0x07, 0x30, 0x0c,
- 0x80, 0x07, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x38, 0x27, 0xba, 0x1c,
- 0x84, 0x68, 0x8a, 0x02, 0x84, 0xa8, 0xba, 0x32, 0x84, 0x28, 0x8b, 0x22,
- 0x38, 0x27, 0x8a, 0x1c, 0x00, 0x00, 0x00, 0x00
- };
+++ /dev/null
-/* XPM */
-static char *configbutton_xpm[] = {
-/* width height num_colors chars_per_pixel */
-" 32 32 2 1",
-/* colors */
-". c None",
-"# c #000000",
-/* pixels */
-"................................",
-"..#....................##.......",
-"..#############.......####......",
-"..###############.....####......",
-"..###############.....####......",
-"..#############.......####......",
-"..#....####...........####......",
-".......####...........####......",
-".......####...........####......",
-".......####...........####......",
-".......####...........####......",
-".......####...........####......",
-".......####...........####......",
-".......####...........####......",
-".......####...........####......",
-".......####...........####......",
-".......####...........####......",
-".......####...........####......",
-".......####...........####......",
-".......####..........######.....",
-".......####.........########....",
-".......####.........###..###....",
-".......####.........##....##....",
-".......####.........##....##....",
-".......####..........#....#.....",
-"................................",
-"...###..###..#...#.###.#..###...",
-"..#....#...#.##..#.#...#.#......",
-"..#....#...#.#.#.#.###.#.#..##..",
-"..#....#...#.#..##.#...#.#...#..",
-"...###..###..#...#.#...#..###...",
-"................................"
-};
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: copy.h,v 1.1 2002/03/11 15:04:58 bdenney Exp $
-/////////////////////////////////////////////////////////////////////////
-#define BX_COPY_BMAP_X 32
-#define BX_COPY_BMAP_Y 32
-
-static unsigned char bx_copy_bmap[(BX_COPY_BMAP_X*BX_COPY_BMAP_Y)] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
- 0x80, 0x60, 0x4e, 0x02, 0x80, 0x90, 0x52, 0x02, 0x80, 0x90, 0x52, 0x02,
- 0x00, 0x6f, 0x8e, 0x03, 0x00, 0x00, 0x02, 0x02, 0xf8, 0x3f, 0x02, 0x02,
- 0x08, 0x20, 0xc0, 0x01, 0xe8, 0x2b, 0x00, 0x00, 0x08, 0x20, 0x00, 0x00,
- 0xe8, 0x2e, 0x00, 0x00, 0x08, 0x20, 0x00, 0x00, 0xe8, 0x39, 0x00, 0x00,
- 0x08, 0x24, 0x00, 0x00, 0x88, 0x20, 0x00, 0x00, 0xe8, 0xaf, 0xff, 0x03,
- 0x08, 0xa0, 0x00, 0x02, 0xf8, 0xbf, 0xbe, 0x02, 0x00, 0x80, 0x00, 0x02,
- 0x80, 0x88, 0xee, 0x02, 0x80, 0x90, 0x00, 0x02, 0x00, 0xbf, 0x9e, 0x03,
- 0x00, 0x90, 0x40, 0x02, 0x00, 0x88, 0x08, 0x02, 0x00, 0x80, 0xfe, 0x02,
- 0x00, 0x80, 0x00, 0x02, 0x00, 0x80, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
+++ /dev/null
-/* XPM */
-static char *copy_xpm[] = {
-/* width height num_colors chars_per_pixel */
-" 32 32 2 1",
-/* colors */
-". c None",
-"# c #000000",
-/* pixels */
-"................................",
-"........####....................",
-".......#........................",
-".......#.....##..###..#..#......",
-".......#....#..#.#..#.#..#......",
-".......#....#..#.#..#.#..#......",
-"........####.##..###...###......",
-".................#.......#......",
-"...###########...#.......#......",
-"...#.........#........###.......",
-"...#.#####.#.#..................",
-"...#.........#..................",
-"...#.###.###.#..................",
-"...#.........#..................",
-"...#.####..###..................",
-"...#......#..#..................",
-"...#...#.....#..................",
-"...#.#######.#.###########......",
-"...#.........#.#.........#......",
-"...###########.#.#####.#.#......",
-"...............#.........#......",
-".......#...#...#.###.###.#......",
-".......#....#..#.........#......",
-"........######.#.####..###......",
-"............#..#......#..#......",
-"...........#...#...#.....#......",
-"...............#.#######.#......",
-"...............#.........#......",
-"...............###########......",
-"................................",
-"................................",
-"................................"
-};
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: floppya.h,v 1.2 2001/10/03 13:10:37 bdenney Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-#define BX_FLOPPYA_BMAP_X 32
-#define BX_FLOPPYA_BMAP_Y 32
-
-static const unsigned char bx_floppya_bmap[(BX_FLOPPYA_BMAP_X * BX_FLOPPYA_BMAP_Y)/8] = {
- 0x00, 0x80, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x40, 0x11, 0x00,
- 0x00, 0xc0, 0x01, 0x00, 0x00, 0x60, 0x13, 0x00, 0x00, 0x60, 0x03, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0x07, 0xe0, 0x01, 0x80, 0x07,
- 0x20, 0xfd, 0xbf, 0x04, 0x20, 0x01, 0x80, 0x04, 0xe0, 0xfd, 0xbf, 0x07,
- 0xe0, 0x01, 0x80, 0x07, 0xe0, 0xfd, 0xbf, 0x07, 0xe0, 0x01, 0x80, 0x07,
- 0xe0, 0xfd, 0xbf, 0x07, 0xe0, 0x01, 0x80, 0x07, 0xe0, 0xfd, 0xbf, 0x07,
- 0xe0, 0x01, 0x80, 0x07, 0xe0, 0xfd, 0xbf, 0x07, 0xe0, 0x01, 0x80, 0x07,
- 0xe0, 0xff, 0xff, 0x07, 0xe0, 0xff, 0xff, 0x07, 0xe0, 0xff, 0xff, 0x07,
- 0xe0, 0xff, 0xff, 0x07, 0xe0, 0xaf, 0xea, 0x07, 0xe0, 0xf7, 0xd5, 0x07,
- 0xe0, 0xef, 0xea, 0x07, 0xe0, 0xf7, 0xd5, 0x07, 0xc0, 0xef, 0xea, 0x07,
- 0x80, 0x57, 0xd5, 0x07, 0x00, 0xaf, 0xea, 0x07
- };
-
-static const unsigned char bx_floppya_eject_bmap[(BX_FLOPPYA_BMAP_X * BX_FLOPPYA_BMAP_Y)/8] = {
- 0x01, 0x80, 0x00, 0x80, 0x02, 0x40, 0x01, 0x40, 0x04, 0x40, 0x11, 0x20,
- 0x08, 0xc0, 0x01, 0x10, 0x10, 0x60, 0x13, 0x08, 0x20, 0x60, 0x03, 0x04,
- 0x40, 0x00, 0x00, 0x02, 0xe0, 0xff, 0xff, 0x07, 0xe0, 0x01, 0x80, 0x07,
- 0x20, 0xff, 0xff, 0x04, 0x20, 0x05, 0xa0, 0x04, 0xe0, 0xfd, 0xbf, 0x07,
- 0xe0, 0x11, 0x88, 0x07, 0xe0, 0xfd, 0xbf, 0x07, 0xe0, 0x41, 0x82, 0x07,
- 0xe0, 0xfd, 0xbf, 0x07, 0xe0, 0x81, 0x81, 0x07, 0xe0, 0xfd, 0xbf, 0x07,
- 0xe0, 0x21, 0x84, 0x07, 0xe0, 0xfd, 0xbf, 0x07, 0xe0, 0x09, 0x90, 0x07,
- 0xe0, 0xff, 0xff, 0x07, 0xe0, 0xff, 0xff, 0x07, 0xe0, 0xff, 0xff, 0x07,
- 0xe0, 0xff, 0xff, 0x07, 0xe0, 0xaf, 0xea, 0x07, 0xe0, 0xf7, 0xd5, 0x07,
- 0xf0, 0xef, 0xea, 0x0f, 0xe8, 0xf7, 0xd5, 0x17, 0xc4, 0xef, 0xea, 0x27,
- 0x82, 0x57, 0xd5, 0x47, 0x01, 0xaf, 0xea, 0x87
- };
+++ /dev/null
-/* XPM */
-static char *floppya_xpm[] = {
-/* width height num_colors chars_per_pixel */
-" 32 32 2 1",
-/* colors */
-". c None",
-"# c #000000",
-/* pixels */
-"...............#................",
-"..............#.#...............",
-"..............#.#...#...........",
-"..............###...............",
-".............##.##..#...........",
-".............##.##..............",
-"................................",
-".....######################.....",
-".....####..............####.....",
-".....#..#.############.#..#.....",
-".....#..#..............#..#.....",
-".....####.############.####.....",
-".....####..............####.....",
-".....####.############.####.....",
-".....####..............####.....",
-".....####.############.####.....",
-".....####..............####.....",
-".....####.############.####.....",
-".....####..............####.....",
-".....####.############.####.....",
-".....####..............####.....",
-".....######################.....",
-".....######################.....",
-".....######################.....",
-".....######################.....",
-".....#######.#.#.#.#.######.....",
-".....######.#####.#.#.#####.....",
-".....#######.###.#.#.######.....",
-".....######.#####.#.#.#####.....",
-"......######.###.#.#.######.....",
-".......####.#.#.#.#.#.#####.....",
-"........####.#.#.#.#.######....."
-};
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: floppyb.h,v 1.2 2001/10/03 13:10:37 bdenney Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-#define BX_FLOPPYB_BMAP_X 32
-#define BX_FLOPPYB_BMAP_Y 32
-
-static const unsigned char bx_floppyb_bmap[(BX_FLOPPYB_BMAP_X * BX_FLOPPYB_BMAP_Y)/8] = {
- 0x00, 0xe0, 0x00, 0x00, 0x00, 0x20, 0x01, 0x00, 0x00, 0xe0, 0x08, 0x00,
- 0x00, 0x20, 0x01, 0x00, 0x00, 0x20, 0x09, 0x00, 0x00, 0xe0, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0x07, 0xe0, 0x01, 0x80, 0x07,
- 0x20, 0xfd, 0xbf, 0x04, 0x20, 0x01, 0x80, 0x04, 0xe0, 0xfd, 0xbf, 0x07,
- 0xe0, 0x01, 0x80, 0x07, 0xe0, 0xfd, 0xbf, 0x07, 0xe0, 0x01, 0x80, 0x07,
- 0xe0, 0xfd, 0xbf, 0x07, 0xe0, 0x01, 0x80, 0x07, 0xe0, 0xfd, 0xbf, 0x07,
- 0xe0, 0x01, 0x80, 0x07, 0xe0, 0xfd, 0xbf, 0x07, 0xe0, 0x01, 0x80, 0x07,
- 0xe0, 0xff, 0xff, 0x07, 0xe0, 0xff, 0xff, 0x07, 0xe0, 0xff, 0xff, 0x07,
- 0xe0, 0xff, 0xff, 0x07, 0xe0, 0xaf, 0xea, 0x07, 0xe0, 0xf7, 0xd5, 0x07,
- 0xe0, 0xef, 0xea, 0x07, 0xe0, 0xf7, 0xd5, 0x07, 0xc0, 0xef, 0xea, 0x07,
- 0x80, 0x57, 0xd5, 0x07, 0x00, 0xaf, 0xea, 0x07
- };
-
-static const unsigned char bx_floppyb_eject_bmap[(BX_FLOPPYB_BMAP_X * BX_FLOPPYB_BMAP_Y)/8] = {
- 0x01, 0xe0, 0x00, 0x80, 0x02, 0x20, 0x01, 0x40, 0x04, 0xe0, 0x08, 0x20,
- 0x08, 0x20, 0x01, 0x10, 0x10, 0x20, 0x09, 0x08, 0x20, 0xe0, 0x00, 0x04,
- 0x40, 0x00, 0x00, 0x02, 0xe0, 0xff, 0xff, 0x07, 0xe0, 0x01, 0x80, 0x07,
- 0x20, 0xff, 0xff, 0x04, 0x20, 0x05, 0xa0, 0x04, 0xe0, 0xfd, 0xbf, 0x07,
- 0xe0, 0x11, 0x88, 0x07, 0xe0, 0xfd, 0xbf, 0x07, 0xe0, 0x41, 0x82, 0x07,
- 0xe0, 0xfd, 0xbf, 0x07, 0xe0, 0x81, 0x81, 0x07, 0xe0, 0xfd, 0xbf, 0x07,
- 0xe0, 0x21, 0x84, 0x07, 0xe0, 0xfd, 0xbf, 0x07, 0xe0, 0x09, 0x90, 0x07,
- 0xe0, 0xff, 0xff, 0x07, 0xe0, 0xff, 0xff, 0x07, 0xe0, 0xff, 0xff, 0x07,
- 0xe0, 0xff, 0xff, 0x07, 0xe0, 0xaf, 0xea, 0x07, 0xe0, 0xf7, 0xd5, 0x07,
- 0xf0, 0xef, 0xea, 0x0f, 0xe8, 0xf7, 0xd5, 0x17, 0xc4, 0xef, 0xea, 0x27,
- 0x82, 0x57, 0xd5, 0x47, 0x01, 0xaf, 0xea, 0x87
- };
+++ /dev/null
-/* XPM */
-static char *floppyb_xpm[] = {
-/* width height num_colors chars_per_pixel */
-" 32 32 2 1",
-/* colors */
-". c None",
-"# c #000000",
-/* pixels */
-".............###................",
-".............#..#...............",
-".............###...#............",
-".............#..#...............",
-".............#..#..#............",
-".............###................",
-"................................",
-".....######################.....",
-".....####..............####.....",
-".....#..#.############.#..#.....",
-".....#..#..............#..#.....",
-".....####.############.####.....",
-".....####..............####.....",
-".....####.############.####.....",
-".....####..............####.....",
-".....####.############.####.....",
-".....####..............####.....",
-".....####.############.####.....",
-".....####..............####.....",
-".....####.############.####.....",
-".....####..............####.....",
-".....######################.....",
-".....######################.....",
-".....######################.....",
-".....######################.....",
-".....#######.#.#.#.#.######.....",
-".....######.#####.#.#.#####.....",
-".....#######.###.#.#.######.....",
-".....######.#####.#.#.#####.....",
-"......######.###.#.#.######.....",
-".......####.#.#.#.#.#.#####.....",
-"........####.#.#.#.#.######....."
-};
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: mouse.h,v 1.2 2001/10/03 13:10:37 bdenney Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-#define BX_MOUSE_BMAP_X 32
-#define BX_MOUSE_BMAP_Y 32
-
-static unsigned char bx_mouse_bmap[(BX_MOUSE_BMAP_X * BX_MOUSE_BMAP_Y)/8] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xf8, 0x1f, 0x00,
- 0x00, 0x0c, 0x30, 0x00, 0x00, 0x06, 0x60, 0x00, 0x00, 0x06, 0x40, 0x00,
- 0xf8, 0xff, 0xc0, 0x00, 0x0c, 0x80, 0xc1, 0x00, 0x24, 0x22, 0xc1, 0x00,
- 0x74, 0x77, 0x81, 0x00, 0x74, 0x77, 0x81, 0x01, 0x74, 0x77, 0x81, 0x01,
- 0x74, 0x77, 0x01, 0x01, 0x74, 0x77, 0x01, 0x03, 0x74, 0x77, 0x01, 0x06,
- 0x24, 0x22, 0x01, 0x0c, 0x0c, 0x80, 0x01, 0x38, 0x04, 0x00, 0x01, 0x00,
- 0x0c, 0x80, 0x01, 0x00, 0x04, 0x00, 0x01, 0x00, 0x0c, 0x80, 0x01, 0x00,
- 0x04, 0x00, 0x01, 0x00, 0x0c, 0x80, 0x01, 0x00, 0x04, 0x00, 0x01, 0x00,
- 0x0c, 0x80, 0x01, 0x00, 0x14, 0x40, 0x01, 0x00, 0x2c, 0xa0, 0x01, 0x00,
- 0x54, 0x55, 0x01, 0x00, 0xac, 0xaa, 0x01, 0x00, 0xf8, 0xff, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
-
-static unsigned char bx_nomouse_bmap[(BX_MOUSE_BMAP_X * BX_MOUSE_BMAP_Y)/8] = {
- 0x01, 0x00, 0x00, 0x80, 0x02, 0xe0, 0x07, 0x40, 0x04, 0xf8, 0x1f, 0x20,
- 0x08, 0x0c, 0x30, 0x10, 0x10, 0x06, 0x60, 0x08, 0x20, 0x06, 0x40, 0x04,
- 0xf8, 0xff, 0xc0, 0x02, 0x8c, 0x80, 0xc1, 0x01, 0x24, 0x23, 0xc1, 0x00,
- 0x74, 0x77, 0xc1, 0x00, 0x74, 0x77, 0xa1, 0x01, 0x74, 0x7f, 0x91, 0x01,
- 0x74, 0x77, 0x09, 0x01, 0x74, 0x77, 0x05, 0x03, 0x74, 0x77, 0x03, 0x06,
- 0x24, 0xa2, 0x01, 0x0c, 0x0c, 0x80, 0x01, 0x38, 0x04, 0x40, 0x03, 0x00,
- 0x0c, 0xa0, 0x05, 0x00, 0x04, 0x10, 0x09, 0x00, 0x0c, 0x88, 0x11, 0x00,
- 0x04, 0x04, 0x21, 0x00, 0x0c, 0x82, 0x41, 0x00, 0x04, 0x01, 0x81, 0x00,
- 0x8c, 0x80, 0x01, 0x01, 0x54, 0x40, 0x01, 0x02, 0x2c, 0xa0, 0x01, 0x04,
- 0x54, 0x55, 0x01, 0x08, 0xac, 0xaa, 0x01, 0x10, 0xfc, 0xff, 0x00, 0x20,
- 0x02, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x80
- };
+++ /dev/null
-/* XPM */
-static char *mouse_xpm[] = {
-/* width height num_colors chars_per_pixel */
-" 32 32 2 1",
-/* colors */
-". c None",
-"# c #000000",
-/* pixels */
-"................................",
-".............######.............",
-"...........##########...........",
-"..........##........##..........",
-".........##..........##.........",
-".........##...........#.........",
-"...#############......##........",
-"..##...........##.....##........",
-"..#..#...#...#..#.....##........",
-"..#.###.###.###.#......#........",
-"..#.###.###.###.#......##.......",
-"..#.###.###.###.#......##.......",
-"..#.###.###.###.#.......#.......",
-"..#.###.###.###.#.......##......",
-"..#.###.###.###.#........##.....",
-"..#..#...#...#..#.........##....",
-"..##...........##..........###..",
-"..#.............#...............",
-"..##...........##...............",
-"..#.............#...............",
-"..##...........##...............",
-"..#.............#...............",
-"..##...........##...............",
-"..#.............#...............",
-"..##...........##...............",
-"..#.#.........#.#...............",
-"..##.#.......#.##...............",
-"..#.#.#.#.#.#.#.#...............",
-"..##.#.#.#.#.#.##...............",
-"...#############................",
-"................................",
-"................................"
-};
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: paste.h,v 1.1 2002/03/11 15:04:58 bdenney Exp $
-/////////////////////////////////////////////////////////////////////////
-#define BX_PASTE_BMAP_X 32
-#define BX_PASTE_BMAP_Y 32
-
-static unsigned char bx_paste_bmap[(BX_PASTE_BMAP_X*BX_PASTE_BMAP_Y)] = {
- 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x10, 0x00, 0x20, 0x9a, 0x93, 0x03,
- 0x20, 0x66, 0x78, 0x04, 0xe0, 0xa5, 0xd3, 0x07, 0x20, 0x24, 0x54, 0x00,
- 0x20, 0xd8, 0x93, 0x03, 0x00, 0x80, 0x01, 0x00, 0x00, 0xc0, 0x02, 0x00,
- 0x00, 0x7c, 0x3f, 0x00, 0xc0, 0x83, 0xc1, 0x03, 0x20, 0x02, 0x40, 0x04,
- 0x20, 0x01, 0x80, 0x04, 0x20, 0x01, 0x80, 0x04, 0xa0, 0xff, 0xff, 0x05,
- 0x20, 0x00, 0x00, 0x04, 0x20, 0x00, 0x00, 0x04, 0x20, 0xf8, 0x3f, 0x04,
- 0x20, 0x08, 0x20, 0x04, 0x20, 0xe8, 0x2b, 0x04, 0x20, 0x08, 0x20, 0x04,
- 0x20, 0xe8, 0x2e, 0x04, 0x20, 0x08, 0x20, 0x04, 0x20, 0xe8, 0x39, 0x04,
- 0x20, 0x08, 0x24, 0x04, 0x20, 0x88, 0x20, 0x04, 0x20, 0xe8, 0x2f, 0x04,
- 0x20, 0x08, 0x20, 0x04, 0x20, 0xf8, 0x3f, 0x04, 0x20, 0x00, 0x00, 0x04,
- 0xc0, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, };
+++ /dev/null
-/* XPM */
-static char *paste_xpm[] = {
-/* width height num_colors chars_per_pixel */
-" 32 32 2 1",
-/* colors */
-". c None",
-"# c #000000",
-/* pixels */
-"................................",
-".....####...........#...........",
-".....#...#.##..###..#..###......",
-".....#...##..##....####...#.....",
-".....####.#..#.###..#.#####.....",
-".....#....#..#....#.#.#.........",
-".....#.....##.####..#..###......",
-"...............##...............",
-"..............##.#..............",
-"..........#####.######..........",
-"......####.....##.....####......",
-".....#...#............#...#.....",
-".....#..#..............#..#.....",
-".....#..#..............#..#.....",
-".....#.##################.#.....",
-".....#....................#.....",
-".....#....................#.....",
-".....#.....###########....#.....",
-".....#.....#.........#....#.....",
-".....#.....#.#####.#.#....#.....",
-".....#.....#.........#....#.....",
-".....#.....#.###.###.#....#.....",
-".....#.....#.........#....#.....",
-".....#.....#.####..###....#.....",
-".....#.....#......#..#....#.....",
-".....#.....#...#.....#....#.....",
-".....#.....#.#######.#....#.....",
-".....#.....#.........#....#.....",
-".....#.....###########....#.....",
-".....#....................#.....",
-"......####################......",
-"................................"
-};
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: power.h,v 1.2 2001/10/03 13:10:37 bdenney Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-#define BX_POWER_BMAP_X 32
-#define BX_POWER_BMAP_Y 32
-
-static const unsigned char bx_power_bmap[(BX_POWER_BMAP_X * BX_POWER_BMAP_Y)/8] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00,
- 0x24, 0x67, 0x66, 0x34, 0xa4, 0x28, 0x92, 0x48, 0x9a, 0xa8, 0xfa, 0x04,
- 0x82, 0x64, 0x09, 0x04, 0x07, 0xa3, 0x70, 0x0e, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xf8, 0x03, 0x00, 0x00, 0xfe, 0x0f, 0x00, 0x00, 0x0f, 0x1e, 0x00,
- 0x80, 0x03, 0x38, 0x00, 0xc0, 0x00, 0x60, 0x00, 0xe0, 0xe0, 0xe0, 0x00,
- 0x60, 0xe0, 0xc0, 0x00, 0x70, 0xe0, 0xc0, 0x01, 0x30, 0xe0, 0x80, 0x01,
- 0x30, 0xe0, 0x80, 0x01, 0x30, 0xe0, 0x80, 0x01, 0x30, 0xe0, 0x80, 0x01,
- 0x30, 0xe0, 0x80, 0x01, 0x70, 0xe0, 0xc0, 0x01, 0x60, 0xe0, 0xc0, 0x00,
- 0xe0, 0xe0, 0xe0, 0x00, 0xc0, 0x00, 0x60, 0x00, 0x80, 0x03, 0x38, 0x00,
- 0x00, 0x0f, 0x1e, 0x00, 0x00, 0xfe, 0x0f, 0x00, 0x00, 0xf8, 0x03, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
+++ /dev/null
-/* XPM */
-static char *power_xpm[] = {
-/* width height num_colors chars_per_pixel */
-" 32 32 2 1",
-/* colors */
-". c None",
-"# c #000000",
-/* pixels */
-"................................",
-"................................",
-".####...........................",
-"..#..#..###..##..##..##...#.##..",
-"..#..#.#...#.#...#..#..#...#..#.",
-".#.##..#...#.#.#.#.#####..#.....",
-".#.....#..#..##.#..#......#.....",
-"###.....##...#.#....###..###....",
-"................................",
-"...........#######..............",
-".........###########............",
-"........####.....####...........",
-".......###.........###..........",
-"......##.............##.........",
-".....###.....###.....###........",
-".....##......###......##........",
-"....###......###......###.......",
-"....##.......###.......##.......",
-"....##.......###.......##.......",
-"....##.......###.......##.......",
-"....##.......###.......##.......",
-"....##.......###.......##.......",
-"....###......###......###.......",
-".....##......###......##........",
-".....###.....###.....###........",
-"......##.............##.........",
-".......###.........###..........",
-"........####.....####...........",
-".........###########............",
-"...........#######..............",
-"................................",
-"................................"
-};
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: reset.h,v 1.2 2001/10/03 13:10:37 bdenney Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-#define BX_RESET_BMAP_X 32
-#define BX_RESET_BMAP_Y 32
-
-static const unsigned char bx_reset_bmap[(BX_RESET_BMAP_X * BX_RESET_BMAP_Y)/8] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x3c, 0x00, 0x00, 0x10,
- 0x48, 0x0c, 0xc7, 0x7c, 0x48, 0x92, 0x20, 0x11, 0x34, 0x1f, 0xf3, 0x09,
- 0x24, 0x41, 0x12, 0x48, 0x6e, 0xce, 0xe1, 0x30, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00,
- 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xf0, 0x1f, 0x00, 0x00, 0xe0, 0x3f, 0x00,
- 0x00, 0xc7, 0x38, 0x00, 0x00, 0x87, 0x38, 0x00, 0x00, 0x07, 0x38, 0x00,
- 0x00, 0x07, 0x38, 0x00, 0x00, 0x07, 0x38, 0x00, 0x00, 0x07, 0x38, 0x00,
- 0x00, 0x07, 0x38, 0x00, 0x00, 0xff, 0x3f, 0x00, 0x00, 0xfe, 0x1f, 0x00,
- 0x00, 0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
+++ /dev/null
-/* XPM */
-static char *reset_xpm[] = {
-/* width height num_colors chars_per_pixel */
-" 32 32 2 1",
-/* colors */
-". c None",
-"# c #000000",
-/* pixels */
-"................................",
-".............................#..",
-"..####......................#...",
-"...#..#...##....###...##..#####.",
-"...#..#..#..#..#.....#..#...#...",
-"..#.##..#####...##..#####..#....",
-"..#..#..#.....#..#..#......#..#.",
-".###.##..###..###....###....##..",
-"................................",
-"................................",
-"................................",
-"................................",
-"................................",
-"...............#................",
-"..............##................",
-".............#######............",
-"............#########...........",
-".............#########..........",
-"........###...##...###..........",
-"........###....#...###..........",
-"........###........###..........",
-"........###........###..........",
-"........###........###..........",
-"........###........###..........",
-"........###........###..........",
-"........##############..........",
-".........############...........",
-"..........##########............",
-"................................",
-"................................",
-"................................",
-"................................"
-};
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: snapshot.h,v 1.2 2001/10/03 13:10:37 bdenney Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-#define BX_SNAPSHOT_BMAP_X 32
-#define BX_SNAPSHOT_BMAP_Y 32
-
-static const unsigned char bx_snapshot_bmap[(BX_SNAPSHOT_BMAP_X * BX_SNAPSHOT_BMAP_Y)/8] = {
- 0x00, 0x00, 0x20, 0x40, 0x77, 0xe6, 0xee, 0xec, 0x91, 0xa8, 0xa2, 0x52,
- 0x96, 0xac, 0xac, 0x52, 0x94, 0xaa, 0xa8, 0x52, 0xb7, 0xee, 0xae, 0xcc,
- 0x00, 0x20, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0x00, 0x08, 0x10, 0x00,
- 0x7c, 0x0f, 0x10, 0x1f, 0xfa, 0x07, 0xa0, 0x2e, 0x42, 0x07, 0xa0, 0x50,
- 0xa3, 0x03, 0xc0, 0xe0, 0xff, 0xee, 0x77, 0xbf, 0x01, 0xf9, 0x9f, 0x40,
- 0x01, 0x1d, 0xb8, 0xa0, 0xff, 0xe5, 0xa7, 0xff, 0xff, 0xba, 0x5a, 0xff,
- 0xff, 0x55, 0xb5, 0xff, 0xff, 0x8d, 0xaa, 0xff, 0xff, 0x16, 0x55, 0xff,
- 0xff, 0xa2, 0x6a, 0xff, 0xff, 0x46, 0x55, 0xff, 0xff, 0xaa, 0x6a, 0xff,
- 0xff, 0x56, 0x55, 0xff, 0xfe, 0xae, 0x6a, 0x7f, 0x00, 0x55, 0xb5, 0x00,
- 0x00, 0xbd, 0xba, 0x00, 0x00, 0xfa, 0x5f, 0x00, 0x00, 0xe4, 0x27, 0x00,
- 0x00, 0x18, 0x18, 0x00, 0x00, 0xe0, 0x07, 0x00
- };
+++ /dev/null
-/* XPM */
-static char *snapshot_xpm[] = {
-/* width height num_colors chars_per_pixel */
-" 32 32 2 1",
-/* colors */
-". c None",
-"# c #000000",
-/* pixels */
-".....................#........#.",
-"###.###..##..###.###.###..##.###",
-"#...#..#...#.#.#.#...#.#.#..#.#.",
-".##.#..#..##.#.#..##.#.#.#..#.#.",
-"..#.#..#.#.#.#.#...#.#.#.#..#.#.",
-"###.##.#.###.###.###.#.#..##..##",
-".............#..................",
-"............########............",
-"...........#........#...........",
-"..#####.####........#...#####...",
-".#.########..........#.#.###.#..",
-".#....#.###..........#.#....#.#.",
-"##...#.###............##.....###",
-"########.###.######.###.######.#",
-"#.......#..##########..#......#.",
-"#.......#.###......###.#.....#.#",
-"#########.#..######..#.#########",
-"########.#.###.#.#.##.#.########",
-"#########.#.#.#.#.#.##.#########",
-"#########.##...#.#.#.#.#########",
-"########.##.#...#.#.#.#.########",
-"########.#...#.#.#.#.##.########",
-"########.##...#.#.#.#.#.########",
-"########.#.#.#.#.#.#.##.########",
-"########.##.#.#.#.#.#.#.########",
-".#######.###.#.#.#.#.##.#######.",
-"........#.#.#.#.#.#.##.#........",
-"........#.####.#.#.###.#........",
-".........#.##########.#.........",
-"..........#..######..#..........",
-"...........##......##...........",
-".............######............."
-};
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: userbutton.h,v 1.1 2002/08/09 06:16:43 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-#define BX_USER_BMAP_X 32
-#define BX_USER_BMAP_Y 32
-
-static const unsigned char bx_user_bmap[BX_USER_BMAP_X*BX_USER_BMAP_Y/8] = {
- 0x00, 0x00, 0x00, 0x00, 0x84, 0x78, 0x9e, 0x07, 0x84, 0x04, 0x82, 0x08,
- 0x84, 0x04, 0x82, 0x08, 0x84, 0x38, 0x9e, 0x07, 0x84, 0x40, 0x82, 0x01,
- 0x84, 0x40, 0x82, 0x06, 0x78, 0x3c, 0x9e, 0x08, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x1c,
- 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, 0x00,
- 0x00, 0x00, 0x80, 0x00, 0xfe, 0xff, 0xff, 0x3f, 0x02, 0x00, 0x00, 0x20,
- 0xaa, 0xaa, 0x2a, 0x2a, 0x02, 0x00, 0x00, 0x20, 0x02, 0x00, 0x00, 0x20,
- 0xaa, 0xaa, 0xaa, 0x2a, 0x52, 0x55, 0x11, 0x25, 0xaa, 0xaa, 0xaa, 0x2a,
- 0x52, 0x55, 0x01, 0x25, 0xaa, 0xaa, 0x82, 0x2a, 0x52, 0x55, 0x11, 0x25,
- 0xaa, 0xbf, 0xaa, 0x2a, 0x02, 0x00, 0x00, 0x20, 0xfe, 0xff, 0xff, 0x3f,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
- };
+++ /dev/null
-/* XPM */
-static char *userbutton_xpm[] = {
-/* columns rows colors chars-per-pixel */
-"32 32 2 1",
-". c None",
-"# c #000000",
-/* pixels */
-"................................",
-"..#....#...####..####..####.....",
-"..#....#..#......#.....#...#....",
-"..#....#..#......#.....#...#....",
-"..#....#...###...####..####.....",
-"..#....#......#..#.....##.......",
-"..#....#......#..#.....#.##.....",
-"...####...####...####..#...#....",
-"................................",
-"................................",
-".............................#..",
-"..........................###...",
-".........................#......",
-"........................#.......",
-".......................#........",
-".......................#........",
-".#############################..",
-".#...........................#..",
-".#.#.#.#.#.#.#.#.#.#.#...#.#.#..",
-".#...........................#..",
-".#...........................#..",
-".#.#.#.#.#.#.#.#.#.#.#.#.#.#.#..",
-".#..#.#.#.#.#.#.#...#...#.#..#..",
-".#.#.#.#.#.#.#.#.#.#.#.#.#.#.#..",
-".#..#.#.#.#.#.#.#.......#.#..#..",
-".#.#.#.#.#.#.#.#.#.....#.#.#.#..",
-".#..#.#.#.#.#.#.#...#...#.#..#..",
-".#.#.#.#######.#.#.#.#.#.#.#.#..",
-".#...........................#..",
-".#############################..",
-"................................",
-"................................"
-};
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: gui.cc,v 1.73 2003/12/18 20:04:48 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-#include <signal.h>
-#include "bochs.h"
-#include "gui/bitmaps/floppya.h"
-#include "gui/bitmaps/floppyb.h"
-#include "gui/bitmaps/mouse.h"
-#include "gui/bitmaps/reset.h"
-#include "gui/bitmaps/power.h"
-#include "gui/bitmaps/snapshot.h"
-#include "gui/bitmaps/copy.h"
-#include "gui/bitmaps/paste.h"
-#include "gui/bitmaps/configbutton.h"
-#include "gui/bitmaps/cdromd.h"
-#include "gui/bitmaps/userbutton.h"
-#if BX_WITH_MACOS
-# include <Disks.h>
-#endif
-
-bx_gui_c *bx_gui = NULL;
-
-#define BX_GUI_THIS bx_gui->
-#define LOG_THIS BX_GUI_THIS
-
-bx_gui_c::bx_gui_c(void)
-{
- put("GUI"); // Init in specific_init
- settype(GUILOG);
-}
-
-bx_gui_c::~bx_gui_c()
-{
-}
-
- void
-bx_gui_c::init(int argc, char **argv, unsigned tilewidth, unsigned tileheight)
-{
- specific_init(argc, argv, tilewidth, tileheight, BX_HEADER_BAR_Y);
-
- // Define some bitmaps to use in the headerbar
- BX_GUI_THIS floppyA_bmap_id = create_bitmap(bx_floppya_bmap,
- BX_FLOPPYA_BMAP_X, BX_FLOPPYA_BMAP_Y);
- BX_GUI_THIS floppyA_eject_bmap_id = create_bitmap(bx_floppya_eject_bmap,
- BX_FLOPPYA_BMAP_X, BX_FLOPPYA_BMAP_Y);
- BX_GUI_THIS floppyB_bmap_id = create_bitmap(bx_floppyb_bmap,
- BX_FLOPPYB_BMAP_X, BX_FLOPPYB_BMAP_Y);
- BX_GUI_THIS floppyB_eject_bmap_id = create_bitmap(bx_floppyb_eject_bmap,
- BX_FLOPPYB_BMAP_X, BX_FLOPPYB_BMAP_Y);
- BX_GUI_THIS cdromD_bmap_id = create_bitmap(bx_cdromd_bmap,
- BX_CDROMD_BMAP_X, BX_CDROMD_BMAP_Y);
- BX_GUI_THIS cdromD_eject_bmap_id = create_bitmap(bx_cdromd_eject_bmap,
- BX_CDROMD_BMAP_X, BX_CDROMD_BMAP_Y);
- BX_GUI_THIS mouse_bmap_id = create_bitmap(bx_mouse_bmap,
- BX_MOUSE_BMAP_X, BX_MOUSE_BMAP_Y);
- BX_GUI_THIS nomouse_bmap_id = create_bitmap(bx_nomouse_bmap,
- BX_MOUSE_BMAP_X, BX_MOUSE_BMAP_Y);
-
-
- BX_GUI_THIS power_bmap_id = create_bitmap(bx_power_bmap, BX_POWER_BMAP_X, BX_POWER_BMAP_Y);
- BX_GUI_THIS reset_bmap_id = create_bitmap(bx_reset_bmap, BX_RESET_BMAP_X, BX_RESET_BMAP_Y);
- BX_GUI_THIS snapshot_bmap_id = create_bitmap(bx_snapshot_bmap, BX_SNAPSHOT_BMAP_X, BX_SNAPSHOT_BMAP_Y);
- BX_GUI_THIS copy_bmap_id = create_bitmap(bx_copy_bmap, BX_COPY_BMAP_X, BX_COPY_BMAP_Y);
- BX_GUI_THIS paste_bmap_id = create_bitmap(bx_paste_bmap, BX_PASTE_BMAP_X, BX_PASTE_BMAP_Y);
- BX_GUI_THIS config_bmap_id = create_bitmap(bx_config_bmap, BX_CONFIG_BMAP_X, BX_CONFIG_BMAP_Y);
- BX_GUI_THIS user_bmap_id = create_bitmap(bx_user_bmap, BX_USER_BMAP_X, BX_USER_BMAP_Y);
-
-
- // Add the initial bitmaps to the headerbar, and enable callback routine, for use
- // when that bitmap is clicked on
-
- // Floppy A:
- BX_GUI_THIS floppyA_status = DEV_floppy_get_media_status(0);
- if (BX_GUI_THIS floppyA_status)
- BX_GUI_THIS floppyA_hbar_id = headerbar_bitmap(BX_GUI_THIS floppyA_bmap_id,
- BX_GRAVITY_LEFT, floppyA_handler);
- else
- BX_GUI_THIS floppyA_hbar_id = headerbar_bitmap(BX_GUI_THIS floppyA_eject_bmap_id,
- BX_GRAVITY_LEFT, floppyA_handler);
-
- // Floppy B:
- BX_GUI_THIS floppyB_status = DEV_floppy_get_media_status(1);
- if (BX_GUI_THIS floppyB_status)
- BX_GUI_THIS floppyB_hbar_id = headerbar_bitmap(BX_GUI_THIS floppyB_bmap_id,
- BX_GRAVITY_LEFT, floppyB_handler);
- else
- BX_GUI_THIS floppyB_hbar_id = headerbar_bitmap(BX_GUI_THIS floppyB_eject_bmap_id,
- BX_GRAVITY_LEFT, floppyB_handler);
-
- // CDROM,
- // valgrinds says that the harddrive object is not be initialised yet,
- // so we just set the bitmap to ejected for now
-#if 0
- if (DEV_hd_present()) {
- Bit32u handle = DEV_hd_get_first_cd_handle();
- BX_GUI_THIS cdromD_status = DEV_hd_get_cd_media_status(handle);
- }
-
- if (BX_GUI_THIS cdromD_status)
- BX_GUI_THIS cdromD_hbar_id = headerbar_bitmap(BX_GUI_THIS cdromD_bmap_id,
- BX_GRAVITY_LEFT, cdromD_handler);
- else
-#endif
- BX_GUI_THIS cdromD_hbar_id = headerbar_bitmap(BX_GUI_THIS cdromD_eject_bmap_id,
- BX_GRAVITY_LEFT, cdromD_handler);
-
- // Mouse button
- if (bx_options.Omouse_enabled->get ())
- BX_GUI_THIS mouse_hbar_id = headerbar_bitmap(BX_GUI_THIS mouse_bmap_id,
- BX_GRAVITY_LEFT, toggle_mouse_enable);
- else
- BX_GUI_THIS mouse_hbar_id = headerbar_bitmap(BX_GUI_THIS nomouse_bmap_id,
- BX_GRAVITY_LEFT, toggle_mouse_enable);
-
- // These are the buttons on the right side. They are created in order
- // of right to left.
-
- // Power button
- BX_GUI_THIS power_hbar_id = headerbar_bitmap(BX_GUI_THIS power_bmap_id,
- BX_GRAVITY_RIGHT, power_handler);
- // Reset button
- BX_GUI_THIS reset_hbar_id = headerbar_bitmap(BX_GUI_THIS reset_bmap_id,
- BX_GRAVITY_RIGHT, reset_handler);
- // Configure button
- BX_GUI_THIS config_hbar_id = headerbar_bitmap(BX_GUI_THIS config_bmap_id,
- BX_GRAVITY_RIGHT, config_handler);
- // Snapshot button
- BX_GUI_THIS snapshot_hbar_id = headerbar_bitmap(BX_GUI_THIS snapshot_bmap_id,
- BX_GRAVITY_RIGHT, snapshot_handler);
- // Paste button
- BX_GUI_THIS paste_hbar_id = headerbar_bitmap(BX_GUI_THIS paste_bmap_id,
- BX_GRAVITY_RIGHT, paste_handler);
- // Copy button
- BX_GUI_THIS copy_hbar_id = headerbar_bitmap(BX_GUI_THIS copy_bmap_id,
- BX_GRAVITY_RIGHT, copy_handler);
- // User button
- BX_GUI_THIS user_hbar_id = headerbar_bitmap(BX_GUI_THIS user_bmap_id,
- BX_GRAVITY_RIGHT, userbutton_handler);
-
- if(bx_options.Otext_snapshot_check->get()) {
- bx_pc_system.register_timer(this, bx_gui_c::snapshot_checker, (unsigned) 1000000, 1, 1, "snap_chk");
- }
-
- BX_GUI_THIS charmap_updated = 0;
-
- show_headerbar();
-}
-
-void
-bx_gui_c::update_drive_status_buttons (void) {
- BX_GUI_THIS floppyA_status =
- DEV_floppy_get_media_status(0)
- && bx_options.floppya.Ostatus->get ();
- BX_GUI_THIS floppyB_status =
- DEV_floppy_get_media_status(1)
- && bx_options.floppyb.Ostatus->get ();
- Bit32u handle = DEV_hd_get_first_cd_handle();
- BX_GUI_THIS cdromD_status = DEV_hd_get_cd_media_status(handle);
- if (BX_GUI_THIS floppyA_status)
- replace_bitmap(BX_GUI_THIS floppyA_hbar_id, BX_GUI_THIS floppyA_bmap_id);
- else {
-#if BX_WITH_MACOS
- // If we are using the Mac floppy driver, eject the disk
- // from the floppy drive. This doesn't work in MacOS X.
- if (!strcmp(bx_options.floppya.Opath->getptr (), SuperDrive))
- DiskEject(1);
-#endif
- replace_bitmap(BX_GUI_THIS floppyA_hbar_id, BX_GUI_THIS floppyA_eject_bmap_id);
- }
- if (BX_GUI_THIS floppyB_status)
- replace_bitmap(BX_GUI_THIS floppyB_hbar_id, BX_GUI_THIS floppyB_bmap_id);
- else {
-#if BX_WITH_MACOS
- // If we are using the Mac floppy driver, eject the disk
- // from the floppy drive. This doesn't work in MacOS X.
- if (!strcmp(bx_options.floppyb.Opath->getptr (), SuperDrive))
- DiskEject(1);
-#endif
- replace_bitmap(BX_GUI_THIS floppyB_hbar_id, BX_GUI_THIS floppyB_eject_bmap_id);
- }
- if (BX_GUI_THIS cdromD_status)
- replace_bitmap(BX_GUI_THIS cdromD_hbar_id, BX_GUI_THIS cdromD_bmap_id);
- else {
- replace_bitmap(BX_GUI_THIS cdromD_hbar_id, BX_GUI_THIS cdromD_eject_bmap_id);
- }
-}
-
- void
-bx_gui_c::floppyA_handler(void)
-{
- if (bx_options.floppya.Odevtype->get() == BX_FLOPPY_NONE)
- return; // no primary floppy device present
-#ifdef WIN32
- if (strcmp(bx_options.Osel_displaylib->get_choice(bx_options.Osel_displaylib->get()),
- "rfb")) {
- // instead of just toggling the status, call win32dialog to bring up
- // a dialog asking what disk image you want to switch to.
- int ret = SIM->ask_param (BXP_FLOPPYA_PATH);
- if (ret > 0) {
- BX_GUI_THIS update_drive_status_buttons ();
- }
- return;
- }
-#endif
- BX_GUI_THIS floppyA_status = !BX_GUI_THIS floppyA_status;
- DEV_floppy_set_media_status(0, BX_GUI_THIS floppyA_status);
- BX_GUI_THIS update_drive_status_buttons ();
-}
-
- void
-bx_gui_c::floppyB_handler(void)
-{
- if (bx_options.floppyb.Odevtype->get() == BX_FLOPPY_NONE)
- return; // no secondary floppy device present
-#ifdef WIN32
- if (strcmp(bx_options.Osel_displaylib->get_choice(bx_options.Osel_displaylib->get()),
- "rfb")) {
- // instead of just toggling the status, call win32dialog to bring up
- // a dialog asking what disk image you want to switch to.
- int ret = SIM->ask_param (BXP_FLOPPYB_PATH);
- if (ret > 0) {
- BX_GUI_THIS update_drive_status_buttons ();
- }
- return;
- }
-#endif
- BX_GUI_THIS floppyB_status = !BX_GUI_THIS floppyB_status;
- DEV_floppy_set_media_status(1, BX_GUI_THIS floppyB_status);
- BX_GUI_THIS update_drive_status_buttons ();
-}
-
- void
-bx_gui_c::cdromD_handler(void)
-{
- Bit32u handle = DEV_hd_get_first_cd_handle();
- if (!strcmp(bx_options.Osel_config->get_choice(bx_options.Osel_config->get()),
- "wx")) {
- // instead of just toggling the status, call wxWindows to bring up
- // a dialog asking what disk image you want to switch to.
- // BBD: for now, find the first cdrom and call ask_param on that.
- // Since we could have multiple cdroms now, maybe we should be adding
- // one cdrom button for each?
- bx_param_c *cdrom = SIM->get_first_cdrom ();
- if (cdrom == NULL)
- return; // no cdrom found
- int ret = SIM->ask_param (cdrom->get_id ());
- if (ret < 0) return; // cancelled
- // eject and then insert the disk. If the new path is invalid,
- // the status will return 0.
- unsigned status = DEV_hd_set_cd_media_status(handle, 0);
- printf ("eject disk, new_status is %d\n", status);
- status = DEV_hd_set_cd_media_status(handle, 1);
- printf ("insert disk, new_status is %d\n", status);
- fflush (stdout);
- BX_GUI_THIS cdromD_status = status;
- } else {
- BX_GUI_THIS cdromD_status =
- DEV_hd_set_cd_media_status(handle, !BX_GUI_THIS cdromD_status);
- }
- BX_GUI_THIS update_drive_status_buttons ();
-}
-
- void
-bx_gui_c::reset_handler(void)
-{
- BX_INFO(( "system RESET callback." ));
- bx_pc_system.ResetSignal( PCS_SET ); /* XXX is this right? */
- for (int i=0; i<BX_SMP_PROCESSORS; i++)
- BX_CPU(i)->reset(BX_RESET_HARDWARE);
-}
-
-#ifdef BX_USE_VMX
-char xm_destroy[PATH_MAX];
-#endif
-
- void
-bx_gui_c::power_handler(void)
-{
- // the user pressed power button, so there's no doubt they want bochs
- // to quit. Change panics to fatal for the GUI and then do a panic.
- bx_user_quit = 1;
- LOG_THIS setonoff(LOGLEV_PANIC, ACT_FATAL);
- BX_INFO(("POWER button turned off."));
- // shouldn't reach this point, but if you do, QUIT!!!
- fprintf (stderr, "Bochs is exiting because you pressed the power button.\n");
- snprintf(xm_destroy, PATH_MAX, "xm destroy %d", domid);
- BX_INFO(("executing: %s\n", xm_destroy));
- if (system(xm_destroy) != 0) {
- BX_PANIC(("failed\n"));
- }
- BX_EXIT (1);
-}
-
-Bit32s
-bx_gui_c::make_text_snapshot (char **snapshot, Bit32u *length)
-{
- Bit8u* raw_snap = NULL;
- char *clean_snap;
- unsigned line_addr, txt_addr, txHeight, txWidth;
-
- DEV_vga_get_text_snapshot(&raw_snap, &txHeight, &txWidth);
- if (txHeight <= 0) return -1;
- clean_snap = (char*) malloc(txHeight*(txWidth+2)+1);
- txt_addr = 0;
- for (unsigned i=0; i<txHeight; i++) {
- line_addr = i * txWidth * 2;
- for (unsigned j=0; j<(txWidth*2); j+=2) {
- clean_snap[txt_addr++] = raw_snap[line_addr+j];
- }
- while ((txt_addr > 0) && (clean_snap[txt_addr-1] == ' ')) txt_addr--;
-#ifdef WIN32
- if(!(bx_options.Otext_snapshot_check->get())) {
- clean_snap[txt_addr++] = 13;
- }
-#endif
- clean_snap[txt_addr++] = 10;
- }
- clean_snap[txt_addr] = 0;
- *snapshot = clean_snap;
- *length = txt_addr;
- return 0;
-}
-
-// create a text snapshot and copy to the system clipboard. On guis that
-// we haven't figured out how to support yet, dump to a file instead.
- void
-bx_gui_c::copy_handler(void)
-{
- Bit32u len;
- char *text_snapshot;
- if (make_text_snapshot (&text_snapshot, &len) < 0) {
- BX_INFO(( "copy button failed, mode not implemented"));
- return;
- }
- if (!BX_GUI_THIS set_clipboard_text(text_snapshot, len)) {
- // platform specific code failed, use portable code instead
- FILE *fp = fopen("copy.txt", "w");
- fwrite(text_snapshot, 1, len, fp);
- fclose(fp);
- }
- free(text_snapshot);
-}
-
-// Check the current text snapshot against file snapchk.txt.
- void
-bx_gui_c::snapshot_checker(void * this_ptr)
-{
- char filename[BX_PATHNAME_LEN];
- strcpy(filename,"snapchk.txt");
- FILE *fp = fopen(filename, "rb");
- if(fp) {
- char *text_snapshot;
- Bit32u len;
- if (make_text_snapshot (&text_snapshot, &len) < 0) {
- return;
- }
- char *compare_snapshot = (char *) malloc((len+1) * sizeof(char));
- fread(compare_snapshot, 1, len, fp);
- fclose(fp);
- strcpy(filename,"snapmask.txt");
- fp=fopen(filename, "rb");
- if(fp) {
- char *mask_snapshot = (char *) malloc((len+1) * sizeof(char));
- unsigned i;
- bx_bool flag = 1;
- fread(mask_snapshot, 1, len, fp);
- fclose(fp);
- for(i=0;i<len;i++) {
- if((text_snapshot[i] != compare_snapshot[i]) &&
- (compare_snapshot[i] == mask_snapshot[i])) {
- flag = 0;
- break;
- }
- }
- if(flag) {
- if(!memcmp(text_snapshot,compare_snapshot,len)) {
- BX_PASS(("Test Passed."));
- } else {
- BX_PASS(("Test Passed with Mask."));
- }
- }
- } else {
- if(!memcmp(text_snapshot,compare_snapshot,len)) {
- BX_PASS(("Test Passed."));
- }
- }
- free(compare_snapshot);
- free(text_snapshot);
- }
-}
-
-// create a text snapshot and dump it to a file
- void
-bx_gui_c::snapshot_handler(void)
-{
- char *text_snapshot;
- Bit32u len;
- if (make_text_snapshot (&text_snapshot, &len) < 0) {
- BX_ERROR(( "snapshot button failed, mode not implemented"));
- return;
- }
- //FIXME
- char filename[BX_PATHNAME_LEN];
-#ifdef WIN32
- if (strcmp(bx_options.Osel_displaylib->get_choice(bx_options.Osel_displaylib->get()),
- "rfb")) {
-#else
- if (!strcmp(bx_options.Osel_config->get_choice(bx_options.Osel_config->get()),
- "wx")) {
-#endif
- int ret = SIM->ask_filename (filename, sizeof(filename),
- "Save snapshot as...", "snapshot.txt",
- bx_param_string_c::SAVE_FILE_DIALOG);
- if (ret < 0) { // cancelled
- free(text_snapshot);
- return;
- }
- } else {
- strcpy (filename, "snapshot.txt");
- }
- FILE *fp = fopen(filename, "wb");
- fwrite(text_snapshot, 1, len, fp);
- fclose(fp);
- free(text_snapshot);
-}
-
-// Read ASCII chars from the system clipboard and paste them into bochs.
-// Note that paste cannot work with the key mapping tables loaded.
- void
-bx_gui_c::paste_handler(void)
-{
- Bit32s nbytes;
- Bit8u *bytes;
- if (!bx_keymap.isKeymapLoaded ()) {
- BX_ERROR (("keyboard_mapping disabled, so paste cannot work"));
- return;
- }
- if (!BX_GUI_THIS get_clipboard_text(&bytes, &nbytes)) {
- BX_ERROR (("paste not implemented on this platform"));
- return;
- }
- BX_INFO (("pasting %d bytes", nbytes));
- DEV_kbd_paste_bytes (bytes, nbytes);
-}
-
-
- void
-bx_gui_c::config_handler(void)
-{
- if (strcmp(bx_options.Osel_displaylib->get_choice(bx_options.Osel_displaylib->get()),
- "rfb")) {
- SIM->configuration_interface (NULL, CI_RUNTIME_CONFIG);
- }
-}
-
- void
-bx_gui_c::toggle_mouse_enable(void)
-{
- int old = bx_options.Omouse_enabled->get ();
- BX_DEBUG (("toggle mouse_enabled, now %d", !old));
- bx_options.Omouse_enabled->set (!old);
-}
-
- void
-bx_gui_c::userbutton_handler(void)
-{
- unsigned shortcut[4];
- unsigned p;
- char *user_shortcut;
- int i, len, ret = 1;
-
- len = 0;
-#ifdef WIN32
- if (strcmp(bx_options.Osel_displaylib->get_choice(bx_options.Osel_displaylib->get()),
- "rfb")) {
-#else
- if (!strcmp(bx_options.Osel_config->get_choice(bx_options.Osel_config->get()),
- "wx")) {
-#endif
- ret = SIM->ask_param (BXP_USER_SHORTCUT);
- }
- user_shortcut = bx_options.Ouser_shortcut->getptr();
- if ((ret > 0) && user_shortcut[0] && (strcmp(user_shortcut, "none"))) {
- len = 0;
- p = 0;
- while ((p < strlen(user_shortcut)) && (len < 3)) {
- if (!strncmp(user_shortcut+p, "alt", 3)) {
- shortcut[len++] = BX_KEY_ALT_L;
- p += 3;
- } else if (!strncmp(user_shortcut+p, "ctrl", 4)) {
- shortcut[len++] = BX_KEY_CTRL_L;
- p += 4;
- } else if (!strncmp(user_shortcut+p, "del", 3)) {
- shortcut[len++] = BX_KEY_DELETE;
- p += 3;
- } else if (!strncmp(user_shortcut+p, "esc", 3)) {
- shortcut[len++] = BX_KEY_ESC;
- p += 3;
- } else if (!strncmp(user_shortcut+p, "f1", 2)) {
- shortcut[len++] = BX_KEY_F1;
- p += 2;
- } else if (!strncmp(user_shortcut+p, "f4", 2)) {
- shortcut[len++] = BX_KEY_F4;
- p += 2;
- } else if (!strncmp(user_shortcut+p, "tab", 3)) {
- shortcut[len++] = BX_KEY_TAB;
- p += 3;
- } else if (!strncmp(user_shortcut+p, "win", 3)) {
- shortcut[len++] = BX_KEY_WIN_L;
- p += 3;
- } else if (!strncmp(user_shortcut+p, "bksp", 4)) {
- shortcut[len++] = BX_KEY_BACKSPACE;
- p += 4;
- } else {
- BX_ERROR(("Unknown shortcut %s ignored", user_shortcut));
- return;
- }
- }
- i = 0;
- while (i < len) {
- DEV_kbd_gen_scancode(shortcut[i++]);
- }
- i--;
- while (i >= 0) {
- DEV_kbd_gen_scancode(shortcut[i--] | BX_KEY_RELEASED);
- }
- }
-}
-
- void
-bx_gui_c::mouse_enabled_changed (bx_bool val)
-{
- // This is only called when SIM->get_init_done is 1. Note that VAL
- // is the new value of mouse_enabled, which may not match the old
- // value which is still in bx_options.Omouse_enabled->get ().
- BX_DEBUG (("replacing the mouse bitmaps"));
- if (val)
- BX_GUI_THIS replace_bitmap(BX_GUI_THIS mouse_hbar_id, BX_GUI_THIS mouse_bmap_id);
- else
- BX_GUI_THIS replace_bitmap(BX_GUI_THIS mouse_hbar_id, BX_GUI_THIS nomouse_bmap_id);
- // give the GUI a chance to respond to the event. Most guis will hide
- // the native mouse cursor and do something to trap the mouse inside the
- // bochs VGA display window.
- BX_GUI_THIS mouse_enabled_changed_specific (val);
-}
-
-void
-bx_gui_c::init_signal_handlers ()
-{
-#if BX_GUI_SIGHANDLER
- if (bx_gui_sighandler)
- {
- Bit32u mask = bx_gui->get_sighandler_mask ();
- for (Bit32u sig=0; sig<32; sig++)
- {
- if (mask & (1<<sig))
- signal (sig, bx_signal_handler);
- }
- }
-#endif
-}
-
- void
-bx_gui_c::set_text_charmap(Bit8u *fbuffer)
-{
- memcpy(& BX_GUI_THIS vga_charmap, fbuffer, 0x2000);
- for (unsigned i=0; i<256; i++) BX_GUI_THIS char_changed[i] = 1;
- BX_GUI_THIS charmap_updated = 1;
-}
-
- void
-bx_gui_c::set_text_charbyte(Bit16u address, Bit8u data)
-{
- BX_GUI_THIS vga_charmap[address] = data;
- BX_GUI_THIS char_changed[address >> 5] = 1;
- BX_GUI_THIS charmap_updated = 1;
-}
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: gui.h,v 1.40 2003/06/28 08:04:31 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-typedef struct {
- Bit8u cs_start;
- Bit8u cs_end;
- Bit16u line_offset;
- Bit16u line_compare;
- Bit8u h_panning;
- Bit8u v_panning;
- bx_bool line_graphics;
-} bx_vga_tminfo_t;
-
-
-BOCHSAPI extern class bx_gui_c *bx_gui;
-
-
-// The bx_gui_c class provides data and behavior that is common to
-// all guis. Each gui implementation will override the abstract methods.
-class BOCHSAPI bx_gui_c : public logfunctions {
-public:
- bx_gui_c (void);
- virtual ~bx_gui_c ();
- // Define the following functions in the module for your particular GUI
- // (x.cc, beos.cc, ...)
- virtual void specific_init(int argc, char **argv,
- unsigned x_tilesize, unsigned y_tilesize, unsigned header_bar_y) = 0;
- virtual void text_update(Bit8u *old_text, Bit8u *new_text,
- unsigned long cursor_x, unsigned long cursor_y,
- bx_vga_tminfo_t tm_info, unsigned rows) = 0;
- virtual void graphics_tile_update(Bit8u *snapshot, unsigned x, unsigned y) = 0;
- virtual void handle_events(void) = 0;
- virtual void flush(void) = 0;
- virtual void clear_screen(void) = 0;
- virtual bx_bool palette_change(unsigned index, unsigned red, unsigned green, unsigned blue) = 0;
- virtual void dimension_update(unsigned x, unsigned y, unsigned fheight=0, unsigned fwidth=0, unsigned bpp=8) = 0;
- virtual unsigned create_bitmap(const unsigned char *bmap, unsigned xdim, unsigned ydim) = 0;
- virtual unsigned headerbar_bitmap(unsigned bmap_id, unsigned alignment, void (*f)(void)) = 0;
- virtual void replace_bitmap(unsigned hbar_id, unsigned bmap_id) = 0;
- virtual void show_headerbar(void) = 0;
- virtual int get_clipboard_text(Bit8u **bytes, Bit32s *nbytes) = 0;
- virtual int set_clipboard_text(char *snapshot, Bit32u len) = 0;
- virtual void mouse_enabled_changed_specific (bx_bool val) = 0;
- virtual void exit(void) = 0;
- // set_display_mode() changes the mode between the configuration interface
- // and the simulation. This is primarily intended for display libraries
- // which have a full-screen mode such as SDL, term, and svgalib. The display
- // mode is set to DISP_MODE_CONFIG before displaying any configuration menus,
- // for panics that requires user input, when entering the debugger, etc. It
- // is set to DISP_MODE_SIM when the Bochs simulation resumes. The
- // enum is defined in gui/siminterface.h.
- virtual void set_display_mode (disp_mode_t newmode) { /* default=no action*/ }
- // These are only needed for the term gui. For all other guis they will
- // have no effect.
- // returns 32-bit bitmask in which 1 means the GUI should handle that signal
- virtual Bit32u get_sighandler_mask () {return 0;}
- // called when registered signal arrives
- virtual void sighandler (int sig) {}
-#if BX_USE_IDLE_HACK
- // this is called from the CPU model when the HLT instruction is executed.
- virtual void sim_is_idle(void) {}
-#endif
-
- // The following function(s) are defined already, and your
- // GUI code calls them
- static void key_event(Bit32u key);
- static void set_text_charmap(Bit8u *fbuffer);
- static void set_text_charbyte(Bit16u address, Bit8u data);
-
- void init(int argc, char **argv,
- unsigned x_tilesize, unsigned y_tilesize);
- void update_drive_status_buttons (void);
- static void mouse_enabled_changed (bx_bool val);
- static void init_signal_handlers ();
-
-
-protected:
- // And these are defined and used privately in gui.cc
- static void floppyA_handler(void);
- static void floppyB_handler(void);
- static void cdromD_handler(void);
- static void reset_handler(void);
- static void power_handler(void);
- static void copy_handler(void);
- static void paste_handler(void);
- static void snapshot_handler(void);
- static void snapshot_checker(void *);
- static void config_handler(void);
- static void toggle_mouse_enable(void);
- static void userbutton_handler(void);
- static Bit32s make_text_snapshot (char **snapshot, Bit32u *length);
-
- bx_bool floppyA_status;
- bx_bool floppyB_status;
- bx_bool cdromD_status;
- unsigned floppyA_bmap_id, floppyA_eject_bmap_id, floppyA_hbar_id;
- unsigned floppyB_bmap_id, floppyB_eject_bmap_id, floppyB_hbar_id;
- unsigned cdromD_bmap_id, cdromD_eject_bmap_id, cdromD_hbar_id;
- unsigned power_bmap_id, power_hbar_id;
- unsigned reset_bmap_id, reset_hbar_id;
- unsigned copy_bmap_id, copy_hbar_id;
- unsigned paste_bmap_id, paste_hbar_id;
- unsigned snapshot_bmap_id, snapshot_hbar_id;
- unsigned config_bmap_id, config_hbar_id;
- unsigned mouse_bmap_id, nomouse_bmap_id, mouse_hbar_id;
- unsigned user_bmap_id, user_hbar_id;
-
- unsigned char vga_charmap[0x2000];
- bx_bool charmap_updated;
- bx_bool char_changed[256];
- disp_mode_t disp_mode;
- };
-
-
-// Add this macro in the class declaration of each GUI, to define all the
-// required virtual methods. Example:
-//
-// class bx_rfb_gui_c : public bx_gui_c {
-// public:
-// bx_rfb_gui_c (void) {}
-// DECLARE_GUI_VIRTUAL_METHODS()
-// };
-// Then, each method must be defined later in the file.
-#define DECLARE_GUI_VIRTUAL_METHODS() \
- virtual void specific_init(int argc, char **argv, \
- unsigned x_tilesize, unsigned y_tilesize, \
- unsigned header_bar_y); \
- virtual void text_update(Bit8u *old_text, Bit8u *new_text, \
- unsigned long cursor_x, unsigned long cursor_y, \
- bx_vga_tminfo_t tm_info, unsigned rows); \
- virtual void graphics_tile_update(Bit8u *snapshot, unsigned x, unsigned y); \
- virtual void handle_events(void); \
- virtual void flush(void); \
- virtual void clear_screen(void); \
- virtual bx_bool palette_change(unsigned index, \
- unsigned red, unsigned green, unsigned blue); \
- virtual void dimension_update(unsigned x, unsigned y, unsigned fheight=0, \
- unsigned fwidth=0, unsigned bpp=8); \
- virtual unsigned create_bitmap(const unsigned char *bmap, \
- unsigned xdim, unsigned ydim); \
- virtual unsigned headerbar_bitmap(unsigned bmap_id, unsigned alignment, \
- void (*f)(void)); \
- virtual void replace_bitmap(unsigned hbar_id, unsigned bmap_id); \
- virtual void show_headerbar(void); \
- virtual int get_clipboard_text(Bit8u **bytes, Bit32s *nbytes); \
- virtual int set_clipboard_text(char *snapshot, Bit32u len); \
- virtual void mouse_enabled_changed_specific (bx_bool val); \
- virtual void exit(void); \
- /* end of DECLARE_GUI_VIRTUAL_METHODS */
-
-#define BX_MAX_PIXMAPS 16
-#define BX_MAX_HEADERBAR_ENTRIES 11
-#define BX_HEADER_BAR_Y 32
-
-// align pixmaps towards left or right side of header bar
-#define BX_GRAVITY_LEFT 10
-#define BX_GRAVITY_RIGHT 11
-
-#define BX_KEY_PRESSED 0x00000000
-#define BX_KEY_RELEASED 0x80000000
-
-#define BX_KEY_UNHANDLED 0x10000000
-
-#define BX_KEY_CTRL_L 0
-#define BX_KEY_SHIFT_L 1
-
-#define BX_KEY_F1 2
-#define BX_KEY_F2 3
-#define BX_KEY_F3 4
-#define BX_KEY_F4 5
-#define BX_KEY_F5 6
-#define BX_KEY_F6 7
-#define BX_KEY_F7 8
-#define BX_KEY_F8 9
-#define BX_KEY_F9 10
-#define BX_KEY_F10 11
-#define BX_KEY_F11 12
-#define BX_KEY_F12 13
-
-#define BX_KEY_CTRL_R 14
-#define BX_KEY_SHIFT_R 15
-#define BX_KEY_CAPS_LOCK 16
-#define BX_KEY_NUM_LOCK 17
-#define BX_KEY_ALT_L 18
-#define BX_KEY_ALT_R 19
-
-#define BX_KEY_A 20
-#define BX_KEY_B 21
-#define BX_KEY_C 22
-#define BX_KEY_D 23
-#define BX_KEY_E 24
-#define BX_KEY_F 25
-#define BX_KEY_G 26
-#define BX_KEY_H 27
-#define BX_KEY_I 28
-#define BX_KEY_J 29
-#define BX_KEY_K 30
-#define BX_KEY_L 31
-#define BX_KEY_M 32
-#define BX_KEY_N 33
-#define BX_KEY_O 34
-#define BX_KEY_P 35
-#define BX_KEY_Q 36
-#define BX_KEY_R 37
-#define BX_KEY_S 38
-#define BX_KEY_T 39
-#define BX_KEY_U 40
-#define BX_KEY_V 41
-#define BX_KEY_W 42
-#define BX_KEY_X 43
-#define BX_KEY_Y 44
-#define BX_KEY_Z 45
-
-#define BX_KEY_0 46
-#define BX_KEY_1 47
-#define BX_KEY_2 48
-#define BX_KEY_3 49
-#define BX_KEY_4 50
-#define BX_KEY_5 51
-#define BX_KEY_6 52
-#define BX_KEY_7 53
-#define BX_KEY_8 54
-#define BX_KEY_9 55
-
-#define BX_KEY_ESC 56
-
-#define BX_KEY_SPACE 57
-#define BX_KEY_SINGLE_QUOTE 58
-#define BX_KEY_COMMA 59
-#define BX_KEY_PERIOD 60
-#define BX_KEY_SLASH 61
-
-#define BX_KEY_SEMICOLON 62
-#define BX_KEY_EQUALS 63
-
-#define BX_KEY_LEFT_BRACKET 64
-#define BX_KEY_BACKSLASH 65
-#define BX_KEY_RIGHT_BRACKET 66
-#define BX_KEY_MINUS 67
-#define BX_KEY_GRAVE 68
-
-#define BX_KEY_BACKSPACE 69
-#define BX_KEY_ENTER 70
-#define BX_KEY_TAB 71
-
-#define BX_KEY_LEFT_BACKSLASH 72
-#define BX_KEY_PRINT 73
-#define BX_KEY_SCRL_LOCK 74
-#define BX_KEY_PAUSE 75
-
-#define BX_KEY_INSERT 76
-#define BX_KEY_DELETE 77
-#define BX_KEY_HOME 78
-#define BX_KEY_END 79
-#define BX_KEY_PAGE_UP 80
-#define BX_KEY_PAGE_DOWN 81
-
-#define BX_KEY_KP_ADD 82
-#define BX_KEY_KP_SUBTRACT 83
-#define BX_KEY_KP_END 84
-#define BX_KEY_KP_DOWN 85
-#define BX_KEY_KP_PAGE_DOWN 86
-#define BX_KEY_KP_LEFT 87
-#define BX_KEY_KP_RIGHT 88
-#define BX_KEY_KP_HOME 89
-#define BX_KEY_KP_UP 90
-#define BX_KEY_KP_PAGE_UP 91
-#define BX_KEY_KP_INSERT 92
-#define BX_KEY_KP_DELETE 93
-#define BX_KEY_KP_5 94
-
-#define BX_KEY_UP 95
-#define BX_KEY_DOWN 96
-#define BX_KEY_LEFT 97
-#define BX_KEY_RIGHT 98
-
-#define BX_KEY_KP_ENTER 99
-#define BX_KEY_KP_MULTIPLY 100
-#define BX_KEY_KP_DIVIDE 101
-
-#define BX_KEY_WIN_L 102
-#define BX_KEY_WIN_R 103
-#define BX_KEY_MENU 104
-
-#define BX_KEY_ALT_SYSREQ 105
-#define BX_KEY_CTRL_BREAK 106
-
-#define BX_KEY_INT_BACK 107
-#define BX_KEY_INT_FORWARD 108
-#define BX_KEY_INT_STOP 109
-#define BX_KEY_INT_MAIL 110
-#define BX_KEY_INT_SEARCH 111
-#define BX_KEY_INT_FAV 112
-#define BX_KEY_INT_HOME 113
-
-#define BX_KEY_POWER_MYCOMP 114
-#define BX_KEY_POWER_CALC 115
-#define BX_KEY_POWER_SLEEP 116
-#define BX_KEY_POWER_POWER 117
-#define BX_KEY_POWER_WAKE 118
-
-#define BX_KEY_NBKEYS 119
-// If you add BX_KEYs Please update
-// - BX_KEY_NBKEYS
-// - the scancodes table in the file iodev/scancodes.cc
-// - the bx_key_symbol table in the file gui/keymap.cc
-
-
-/////////////// GUI plugin support
-
-// Define macro to supply gui plugin code. This macro is called once in GUI to
-// supply the plugin initialization methods. Since it is nearly identical for
-// each gui module, the macro is easier to maintain than pasting the same code
-// in each one.
-//
-// Each gui should declare a class pointer called "theGui" which is derived
-// from bx_gui_c, before calling this macro. For example, the SDL port
-// says:
-// static bx_sdl_gui_c *theGui;
-
-#define IMPLEMENT_GUI_PLUGIN_CODE(gui_name) \
- int lib##gui_name##_LTX_plugin_init(plugin_t *plugin, \
- plugintype_t type, int argc, char *argv[]) { \
- genlog->info("installing %s module as the Bochs GUI", #gui_name); \
- theGui = new bx_##gui_name##_gui_c (); \
- bx_gui = theGui; \
- return(0); /* Success */ \
- } \
- void lib##gui_name##_LTX_plugin_fini(void) { }
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: icon_bochs.h,v 1.3 2001/10/03 13:10:37 bdenney Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2001 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-#define bochs_icon_width 32
-#define bochs_icon_height 32
-static unsigned char bochs_icon_bits[] = {
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00,
- 0xe0, 0xff, 0xff, 0x07, 0xf8, 0xff, 0xff, 0x1f, 0xf8, 0xff, 0xff, 0x1f,
- 0xfc, 0xc7, 0xe3, 0x3f, 0xfc, 0xc7, 0xe3, 0x3f, 0xfc, 0xc3, 0xc3, 0x3f,
- 0xfc, 0xc3, 0xc3, 0x3f, 0xf8, 0xc1, 0x83, 0x1f, 0xf0, 0xc0, 0x03, 0x0f,
- 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00,
- 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00,
- 0x00, 0xc0, 0x03, 0x00, 0x00, 0xc0, 0x03, 0x00, 0xf0, 0xc0, 0x03, 0x0f,
- 0xf8, 0xc1, 0x83, 0x1f, 0xfc, 0xc3, 0xc3, 0x3f, 0xfc, 0xc3, 0xc3, 0x3f,
- 0xfc, 0xc7, 0xe3, 0x3f, 0xfc, 0xc7, 0xe3, 0x3f, 0xf8, 0xff, 0xff, 0x1f,
- 0xf8, 0xff, 0xff, 0x1f, 0xe0, 0xff, 0xff, 0x07, 0x00, 0xff, 0xff, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
+++ /dev/null
-/* XPM */
-static char *icon_bochs_xpm[] = {
-/* columns rows colors chars-per-pixel */
-"32 32 7 1",
-" c black",
-". c #800000",
-"X c #808000",
-"o c yellow",
-"O c #808080",
-"+ c #c0c0c0",
-"@ c None",
-/* pixels */
-"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@",
-"@@@@@@@@@@. +@@@+ +@@@@@@@@@",
-"@@@@@@@@ Oo @+ .@@@@@@@@",
-"@@@@@@ ooooo ooo. @@@@@@@",
-"@@@@ oooooo. oooooX @@@@@",
-"@+ XoooooO XX ooooooo O@@@",
-"+ oooooO XXXX X ooooooo @@",
-"@ ooo XXXXXX XX ooooooX ",
-"@@. XXXXXXXX XXX Xooooo. ",
-"@@@@ OXXXXXXXXX XXXXXO oO .@",
-"@@@@ .XXXXXXX XXXXXXX. @@@",
-"@+ oo XXXX XXXXXXXX @@@",
-"@ ooooo XXXXXX O",
-"@@O oooooo OXXXX. XX Oooo ",
-"@@@@ .ooooo. XXXXX oooo O@",
-"@@@@ Oooooo XX. .ooo @@@",
-"@@@@ XX oooooo .oooo. @@@@",
-"@@@@ ooXX . ooO o @@@@",
-"@@@@ oooXX. .Xo XX XXo @@@@",
-"@@@@ ooooXXXXXXXo XXXX.XXoo @@@@",
-"@@@+ oooooooooooo XooXXXooo @@@@",
-"@@@. oooooooooooo Xooooooo @@@@",
-"@@@+ oooooooooo XoooooX .@@@@@",
-"@@@@@O XoooooooX ooooo +@@@@@@",
-"@@@@@@@ ooooooX oooX @@@@@@@@",
-"@@@@@@@@@ ooooX oo @@@@@@@@@",
-"@@@@@@@@@@. Ooo. O@@@@@@@@@@",
-"@@@@@@@@@@@@ @@@@@@@@@@@@",
-"@@@@@@@@@@@@@@O O@@@@@@@@@@@@@",
-"@@@@@@@@@@@@@@@@+@@@@@@@@@@@@@@@",
-"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@",
-"@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"
-};
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: keymap.cc,v 1.16 2003/10/11 10:43:24 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-/////////////////////////////////////////////////////////////////////////
-//
-// Todo
-// . Currently supported by sdl, wxGTK and x11. Check if other guis need mapping.
-// . Tables look-up should be optimised.
-//
-
-#include "bochs.h"
-
-// Table of bochs "BX_KEY_*" symbols
-// the table must be in BX_KEY_* order
-char *bx_key_symbol[BX_KEY_NBKEYS] = {
- "BX_KEY_CTRL_L", "BX_KEY_SHIFT_L", "BX_KEY_F1",
- "BX_KEY_F2", "BX_KEY_F3", "BX_KEY_F4",
- "BX_KEY_F5", "BX_KEY_F6", "BX_KEY_F7",
- "BX_KEY_F8", "BX_KEY_F9", "BX_KEY_F10",
- "BX_KEY_F11", "BX_KEY_F12", "BX_KEY_CTRL_R",
- "BX_KEY_SHIFT_R", "BX_KEY_CAPS_LOCK", "BX_KEY_NUM_LOCK",
- "BX_KEY_ALT_L", "BX_KEY_ALT_R", "BX_KEY_A",
- "BX_KEY_B", "BX_KEY_C", "BX_KEY_D",
- "BX_KEY_E", "BX_KEY_F", "BX_KEY_G",
- "BX_KEY_H", "BX_KEY_I", "BX_KEY_J",
- "BX_KEY_K", "BX_KEY_L", "BX_KEY_M",
- "BX_KEY_N", "BX_KEY_O", "BX_KEY_P",
- "BX_KEY_Q", "BX_KEY_R", "BX_KEY_S",
- "BX_KEY_T", "BX_KEY_U", "BX_KEY_V",
- "BX_KEY_W", "BX_KEY_X", "BX_KEY_Y",
- "BX_KEY_Z", "BX_KEY_0", "BX_KEY_1",
- "BX_KEY_2", "BX_KEY_3", "BX_KEY_4",
- "BX_KEY_5", "BX_KEY_6", "BX_KEY_7",
- "BX_KEY_8", "BX_KEY_9", "BX_KEY_ESC",
- "BX_KEY_SPACE", "BX_KEY_SINGLE_QUOTE", "BX_KEY_COMMA",
- "BX_KEY_PERIOD", "BX_KEY_SLASH", "BX_KEY_SEMICOLON",
- "BX_KEY_EQUALS", "BX_KEY_LEFT_BRACKET", "BX_KEY_BACKSLASH",
- "BX_KEY_RIGHT_BRACKET", "BX_KEY_MINUS", "BX_KEY_GRAVE",
- "BX_KEY_BACKSPACE", "BX_KEY_ENTER", "BX_KEY_TAB",
- "BX_KEY_LEFT_BACKSLASH", "BX_KEY_PRINT", "BX_KEY_SCRL_LOCK",
- "BX_KEY_PAUSE", "BX_KEY_INSERT", "BX_KEY_DELETE",
- "BX_KEY_HOME", "BX_KEY_END", "BX_KEY_PAGE_UP",
- "BX_KEY_PAGE_DOWN", "BX_KEY_KP_ADD", "BX_KEY_KP_SUBTRACT",
- "BX_KEY_KP_END", "BX_KEY_KP_DOWN", "BX_KEY_KP_PAGE_DOWN",
- "BX_KEY_KP_LEFT", "BX_KEY_KP_RIGHT", "BX_KEY_KP_HOME",
- "BX_KEY_KP_UP", "BX_KEY_KP_PAGE_UP", "BX_KEY_KP_INSERT",
- "BX_KEY_KP_DELETE", "BX_KEY_KP_5", "BX_KEY_UP",
- "BX_KEY_DOWN", "BX_KEY_LEFT", "BX_KEY_RIGHT",
- "BX_KEY_KP_ENTER", "BX_KEY_KP_MULTIPLY", "BX_KEY_KP_DIVIDE",
- "BX_KEY_WIN_L", "BX_KEY_WIN_R", "BX_KEY_MENU",
- "BX_KEY_ALT_SYSREQ", "BX_KEY_CTRL_BREAK", "BX_KEY_INT_BACK",
- "BX_KEY_INT_FORWARD", "BX_KEY_INT_STOP", "BX_KEY_INT_MAIL",
- "BX_KEY_INT_SEARCH", "BX_KEY_INT_FAV", "BX_KEY_INT_HOME",
- "BX_KEY_POWER_MYCOMP", "BX_KEY_POWER_CALC", "BX_KEY_POWER_SLEEP",
- "BX_KEY_POWER_POWER", "BX_KEY_POWER_WAKE",
- };
-
-bx_keymap_c bx_keymap;
-
-#define LOG_THIS bx_keymap.
-
-bx_keymap_c::bx_keymap_c(void)
-{
- put("KMAP");
-
- keymapCount = 0;
- keymapTable = (BXKeyEntry *)NULL;
-
-}
-
-bx_keymap_c::~bx_keymap_c(void)
-{
- if(keymapTable != NULL) {
- free(keymapTable);
- keymapTable = (BXKeyEntry *)NULL;
- }
- keymapCount = 0;
-}
-
- void
-bx_keymap_c::loadKeymap(Bit32u stringToSymbol(const char*))
-{
- if(bx_options.keyboard.OuseMapping->get()) {
- loadKeymap(stringToSymbol,bx_options.keyboard.Okeymap->getptr());
- }
-}
-
-
-bx_bool
-bx_keymap_c::isKeymapLoaded ()
-{
- return (keymapCount > 0);
-}
-
-
-///////////////////
-// I'll add these to the keymap object in a minute.
-static unsigned char *lineptr = NULL;
-static int lineCount;
-
-static void
-init_parse ()
-{
- lineCount = 0;
-}
-
-static void
-init_parse_line (char *line_to_parse)
-{
- // chop off newline
- lineptr = (unsigned char *)line_to_parse;
- char *nl;
- if( (nl = strchr(line_to_parse,'\n')) != NULL) {
- *nl = 0;
- }
-}
-
-static Bit32s
-get_next_word (char *output)
-{
- char *copyp = output;
- // find first nonspace
- while (*lineptr && isspace (*lineptr))
- lineptr++;
- if (!*lineptr)
- return -1; // nothing but spaces until end of line
- if (*lineptr == '#')
- return -1; // nothing but a comment
- // copy nonspaces into the output
- while (*lineptr && !isspace (*lineptr))
- *copyp++ = *lineptr++;
- *copyp=0; // null terminate the copy
- // there must be at least one nonspace, since that's why we stopped the
- // first loop!
- BX_ASSERT (copyp != output);
- return 0;
-}
-
-static Bit32s
-get_next_keymap_line (FILE *fp, char *bxsym, char *modsym, Bit32s *ascii, char *hostsym)
-{
- char line[256];
- char buf[256];
- line[0] = 0;
- while (1) {
- lineCount++;
- if (!fgets(line, sizeof(line)-1, fp)) return -1; // EOF
- init_parse_line (line);
- if (get_next_word (bxsym) >= 0) {
- modsym[0] = 0;
- char *p;
- if ((p = strchr (bxsym, '+')) != NULL) {
- *p = 0; // truncate bxsym.
- p++; // move one char beyond the +
- strcpy (modsym, p); // copy the rest to modsym
- }
- if (get_next_word (buf) < 0) {
- BX_PANIC (("keymap line %d: expected 3 columns", lineCount));
- return -1;
- }
- if (buf[0] == '\'' && buf[2] == '\'' && buf[3]==0) {
- *ascii = (Bit8u) buf[1];
- } else if (!strcmp(buf, "space")) {
- *ascii = ' ';
- } else if (!strcmp(buf, "return")) {
- *ascii = '\n';
- } else if (!strcmp(buf, "tab")) {
- *ascii = '\t';
- } else if (!strcmp(buf, "backslash")) {
- *ascii = '\\';
- } else if (!strcmp(buf, "apostrophe")) {
- *ascii = '\'';
- } else if (!strcmp(buf, "none")) {
- *ascii = -1;
- } else {
- BX_PANIC (("keymap line %d: ascii equivalent is \"%s\" but it must be char constant like 'x', or one of space,tab,return,none", lineCount, buf));
- }
- if (get_next_word (hostsym) < 0) {
- BX_PANIC (("keymap line %d: expected 3 columns", lineCount));
- return -1;
- }
- return 0;
- }
- // no words on this line, keep reading.
- }
-}
-
- void
-bx_keymap_c::loadKeymap(Bit32u stringToSymbol(const char*), const char* filename)
-{
- FILE *keymapFile;
- char baseSym[256], modSym[256], hostSym[256];
- Bit32s ascii;
- Bit32u baseKey, modKey, hostKey;
- struct stat status;
-
- if (stat(filename, &status)) {
- BX_PANIC(("Can not stat keymap file '%s'.",filename));
- }
-
- if (!(S_ISREG(status.st_mode))) {
- BX_PANIC(("Keymap file '%s' is not a file",filename));
- }
-
- if((keymapFile = fopen(filename,"r"))==NULL) {
- BX_PANIC(("Can not open keymap file '%s'.",filename));
- }
-
- BX_INFO(("Loading keymap from '%s'",filename));
- init_parse ();
-
- // Read keymap file one line at a time
- while(1) {
- if (get_next_keymap_line (keymapFile,
- baseSym, modSym, &ascii, hostSym) < 0) { break; }
-
-
- // convert X_KEY_* symbols to values
- baseKey = convertStringToBXKey(baseSym);
- modKey = convertStringToBXKey(modSym);
- hostKey = 0;
- if (stringToSymbol != NULL)
- hostKey = stringToSymbol(hostSym);
-
- BX_DEBUG (("baseKey='%s' (%d), modSym='%s' (%d), ascii=%d, guisym='%s' (%d)", baseSym, baseKey, modSym, modKey, ascii, hostSym, hostKey));
-
- // Check if data is valid
- if( baseKey==BX_KEYMAP_UNKNOWN ) {
- BX_PANIC (("line %d: unknown BX_KEY constant '%s'",lineCount,baseSym));
- continue;
- }
-
- if( hostKey==BX_KEYMAP_UNKNOWN ) {
- BX_PANIC (("line %d: unknown host key name '%s'",lineCount,hostSym));
- continue;
- }
-
- keymapTable=(BXKeyEntry*)realloc(keymapTable,(keymapCount+1) * sizeof(BXKeyEntry));
-
- if(keymapTable==NULL)
- BX_PANIC(("Can not allocate memory for keymap table."));
-
- keymapTable[keymapCount].baseKey=baseKey;
- keymapTable[keymapCount].modKey=modKey;
- keymapTable[keymapCount].ascii=ascii;
- keymapTable[keymapCount].hostKey=hostKey;
-
- keymapCount++;
- }
-
- BX_INFO(("Loaded %d symbols",keymapCount));
-
- fclose(keymapFile);
-}
-
- Bit32u
-bx_keymap_c::convertStringToBXKey(const char* string)
-{
- Bit16u i;
-
- // We look through the bx_key_symbol table to find the searched string
- for (i=0; i<BX_KEY_NBKEYS; i++) {
- if (strcmp(string,bx_key_symbol[i])==0) {
- return i;
- }
- }
-
- // Key is not known
- return BX_KEYMAP_UNKNOWN;
-}
-
- BXKeyEntry *
-bx_keymap_c::findHostKey(Bit32u key)
-{
- Bit16u i;
-
- // We look through the keymap table to find the searched key
- for (i=0; i<keymapCount; i++) {
- if (keymapTable[i].hostKey == key) {
- BX_DEBUG (("key 0x%02x matches hostKey for entry #%d", key, i));
- return &keymapTable[i];
- }
- }
- BX_DEBUG (("key %02x matches no entries", key));
-
- // Return default
- return NULL;
-}
-
- BXKeyEntry *
-bx_keymap_c::findAsciiChar(Bit8u ch)
-{
- Bit16u i;
- BX_DEBUG (("findAsciiChar (0x%02x)", ch));
-
- // We look through the keymap table to find the searched key
- for (i=0; i<keymapCount; i++) {
- if (keymapTable[i].ascii == ch) {
- BX_DEBUG (("key %02x matches ascii for entry #%d", ch, i));
- return &keymapTable[i];
- }
- }
- BX_DEBUG (("key 0x%02x matches no entries", ch));
-
- // Return default
- return NULL;
-}
-
- char *
-bx_keymap_c::getBXKeyName(Bit32u key)
-{
- return bx_key_symbol[key & 0x7fffffff];
-}
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: keymap.h,v 1.9 2003/07/12 08:17:10 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-/////////////////////////////////////////////////////////////////////////
-//
-// Methods of bx_keymap_c :
-//
-// - loadKeymap(Bit32u convertStringToSymbol(const char*));
-// loads the configuration specified keymap file if keymapping is enabled
-// using convertStringToSymbol to convert strings to client constants
-//
-// - loadKeymap(Bit32u convertStringToSymbol(const char*), const char* filename);
-// loads the specified keymap file
-// using convertStringToSymbol to convert strings to client constants
-//
-// - isKeymapLoaded () returns true if the keymap contains any valid key
-// entries.
-//
-// - convertStringToBXKey
-// convert a null-terminate string to a BX_KEY code
-//
-// - findHostKey(Bit32u key)
-// - findAsciiChar(Bit8u ch)
-// Each of these methods returns a pointer to a BXKeyEntry structure
-// corresponding to a key. findHostKey() finds an entry whose hostKey
-// value matches the target value, and findAsciiChar() finds an entry
-// whose ASCII code matches the search value.
-
-// In case of unknown symbol
-#define BX_KEYMAP_UNKNOWN 0xFFFFFFFF
-
-// Structure of an element of the keymap table
-typedef struct BOCHSAPI {
- Bit32u baseKey; // base key
- Bit32u modKey; // modifier key that must be held down
- Bit32s ascii; // ascii equivalent, if any
- Bit32u hostKey; // value that the host's OS or library recognizes
- } BXKeyEntry;
-
-class BOCHSAPI bx_keymap_c : public logfunctions {
-public:
- bx_keymap_c(void);
- ~bx_keymap_c(void);
-
- void loadKeymap(Bit32u(*)(const char*));
- void loadKeymap(Bit32u(*)(const char*),const char *filename);
- bx_bool isKeymapLoaded ();
-
- BXKeyEntry *findHostKey(Bit32u hostkeynum);
- BXKeyEntry *findAsciiChar(Bit8u ascii);
- char *getBXKeyName(Bit32u key);
-
-private:
- Bit32u convertStringToBXKey(const char *);
-
- BXKeyEntry *keymapTable;
- Bit16u keymapCount;
- };
-
-BOCHSAPI extern bx_keymap_c bx_keymap;
+++ /dev/null
-#!/usr/bin/perl
-# little utility script that I used to convert key map files from
-# the pre-March 11 format to the post-March 11 format. It doesn't
-# do anything smart with the ascii equivalents and modifiers, so ATM those must
-# be added by hand.
-
-while (<STDIN>)
-{
- chop;
- s/^ *//;
- if (/^#/ || /^ *$/) { print "$_\n"; next;}
- ($key, $equals, $xksym) = split (/ +/);
- printf ("%-45s %-10s %s\n", $key, 'none', "XK_$xksym");
-}
+++ /dev/null
-# Bochs Keymap file
-# $Id: sdl-pc-de.map,v 1.2 2002/10/24 21:06:55 bdenney Exp $
-# Target: PC(x86) keyboard, DE keymap, SDL gui on X11
-# Author: Volker Ruppert
-#
-# The keymap file describes the layout of a keyboard, and how it translates
-# into Bochs key codes.
-#
-# Format:
-# BX_Keysym ASCII_equivalent Host_key_name
-#
-# Or, for keys that require modifiers:
-# BX_Keysym+BX_Modifier ASCII_equivalent Host_key_name
-#
-# BX_Keysym and BX_Modifier must be present in the bx_key_symbol[] list in
-# gui/keymap.cc. The BX_Modifier is usually a shift key press, but it
-# could be any key. Presently a maximum of one modifier is supported, but this
-# could be changed in keymap.h (structure def has only one slot for modifier),
-# keymap.cc (parsing code), and iodev/keyboard.cc (simulate keypresses for >1
-# modifier).
-#
-# The ASCII_equivalent must be either apostrophe + one character + apostrophe,
-# or one of these keywords: space, return, tab, backslash, apostrophe, none.
-# This format is designed to look like a char constant in C, but it's a very
-# simple parser. There's no concept of backslash being an escape char. The
-# backslash and apostrophe entries are provided for aesthetic purposes only: no
-# C++ programmer wants to see '\' or '''. The parser doesn't care, but they are
-# ugly.
-#
-# Host_key_name is the name of the key combination according to the gui library
-# (X windows, SDL, etc). Each GUI module must provide a function that converts
-# these host key names into numbers. A pointer to the conversion function is
-# passed to loadKeymap(), and it is used when parsing the keymap file. As the
-# keymap file is parsed, the conversion function is called for each host key
-# name, to convert it into a number. Only the number is stored. If the host
-# key name is not found, the conversion function returns BX_KEYMAP_UNKNOWN, and
-# the keymap code will panic, like this:
-#
-# [KMAP ] line 51: unknown host key name 'SDLK_PAREN_RIGHT'
-#
-# If this happens, you must edit the keymap file, and either correct the host
-# key name or comment out that line.
-#
-
-BX_KEY_0 '0' SDLK_0
-BX_KEY_0+BX_KEY_SHIFT_L '=' SDLK_EQUALS
-BX_KEY_1 '1' SDLK_1
-BX_KEY_1+BX_KEY_SHIFT_L '!' SDLK_EXCLAIM
-BX_KEY_2 '2' SDLK_2
-BX_KEY_2+BX_KEY_ALT_R '²' SDLK_2
-BX_KEY_2+BX_KEY_SHIFT_L '"' SDLK_QUOTEDBL
-BX_KEY_3 '3' SDLK_3
-BX_KEY_3+BX_KEY_SHIFT_L '§' SDLK_3
-BX_KEY_4 '4' SDLK_4
-BX_KEY_4+BX_KEY_SHIFT_L '$' SDLK_DOLLAR
-BX_KEY_4+BX_KEY_ALT_R '¼' SDLK_4
-BX_KEY_5 '5' SDLK_5
-BX_KEY_5+BX_KEY_ALT_R '½' SDLK_5
-BX_KEY_5+BX_KEY_SHIFT_L '%' SDLK_5
-BX_KEY_6 '6' SDLK_6
-BX_KEY_6+BX_KEY_SHIFT_L '&' SDLK_AMPERSAND
-BX_KEY_7 '7' SDLK_7
-BX_KEY_7+BX_KEY_ALT_R '{' SDLK_7
-BX_KEY_7+BX_KEY_SHIFT_L '/' SDLK_SLASH
-BX_KEY_8 '8' SDLK_8
-BX_KEY_8+BX_KEY_ALT_R '[' SDLK_LEFTBRACKET
-BX_KEY_8+BX_KEY_SHIFT_L '(' SDLK_LEFTPAREN
-BX_KEY_9 '9' SDLK_9
-BX_KEY_9+BX_KEY_ALT_R ']' SDLK_RIGHTBRACKET
-BX_KEY_9+BX_KEY_SHIFT_L ')' SDLK_RIGHTPAREN
-BX_KEY_A+BX_KEY_SHIFT_L 'A' SDLK_a
-BX_KEY_A 'a' SDLK_a
-BX_KEY_A+BX_KEY_ALT_R 'æ' SDLK_a
-BX_KEY_B+BX_KEY_SHIFT_L 'B' SDLK_b
-BX_KEY_B 'b' SDLK_b
-BX_KEY_C+BX_KEY_SHIFT_L 'C' SDLK_c
-BX_KEY_C 'c' SDLK_c
-BX_KEY_C+BX_KEY_ALT_R '¢' SDLK_c
-BX_KEY_D+BX_KEY_SHIFT_L 'D' SDLK_d
-BX_KEY_D 'd' SDLK_d
-BX_KEY_E+BX_KEY_SHIFT_L 'E' SDLK_e
-BX_KEY_E+BX_KEY_ALT_R none SDLK_EURO
-BX_KEY_E 'e' SDLK_e
-BX_KEY_F+BX_KEY_SHIFT_L 'F' SDLK_f
-BX_KEY_F 'f' SDLK_f
-BX_KEY_G+BX_KEY_SHIFT_L 'G' SDLK_g
-BX_KEY_G 'g' SDLK_g
-BX_KEY_H+BX_KEY_SHIFT_L 'H' SDLK_h
-BX_KEY_H 'h' SDLK_h
-BX_KEY_I+BX_KEY_SHIFT_L 'I' SDLK_i
-BX_KEY_I 'i' SDLK_i
-BX_KEY_J+BX_KEY_SHIFT_L 'J' SDLK_j
-BX_KEY_J 'j' SDLK_j
-BX_KEY_K+BX_KEY_SHIFT_L 'K' SDLK_k
-BX_KEY_K 'k' SDLK_k
-BX_KEY_L+BX_KEY_SHIFT_L 'L' SDLK_l
-BX_KEY_L 'l' SDLK_l
-BX_KEY_M+BX_KEY_SHIFT_L 'M' SDLK_m
-BX_KEY_M 'm' SDLK_m
-BX_KEY_M+BX_KEY_ALT_R 'µ' SDLK_m
-BX_KEY_N+BX_KEY_SHIFT_L 'N' SDLK_n
-BX_KEY_N 'n' SDLK_n
-BX_KEY_O+BX_KEY_SHIFT_L 'O' SDLK_o
-BX_KEY_O 'o' SDLK_o
-BX_KEY_O+BX_KEY_ALT_R 'ø' SDLK_o
-BX_KEY_P+BX_KEY_SHIFT_L 'P' SDLK_p
-BX_KEY_P 'p' SDLK_p
-BX_KEY_Q+BX_KEY_SHIFT_L 'Q' SDLK_q
-BX_KEY_Q+BX_KEY_ALT_R '@' SDLK_AT
-BX_KEY_Q 'q' SDLK_q
-BX_KEY_R+BX_KEY_SHIFT_L 'R' SDLK_r
-BX_KEY_R+BX_KEY_ALT_R '¶' SDLK_r
-BX_KEY_R 'r' SDLK_r
-BX_KEY_S+BX_KEY_SHIFT_L 'S' SDLK_s
-BX_KEY_S 's' SDLK_s
-BX_KEY_T+BX_KEY_SHIFT_L 'T' SDLK_t
-BX_KEY_T 't' SDLK_t
-BX_KEY_U+BX_KEY_SHIFT_L 'U' SDLK_u
-BX_KEY_U 'u' SDLK_u
-BX_KEY_V+BX_KEY_SHIFT_L 'V' SDLK_v
-BX_KEY_V 'v' SDLK_v
-BX_KEY_W+BX_KEY_SHIFT_L 'W' SDLK_w
-BX_KEY_W 'w' SDLK_w
-BX_KEY_X+BX_KEY_SHIFT_L 'X' SDLK_x
-BX_KEY_X+BX_KEY_ALT_R '»' SDLK_x
-BX_KEY_X 'x' SDLK_x
-BX_KEY_Y+BX_KEY_SHIFT_L 'Z' SDLK_z
-BX_KEY_Y 'z' SDLK_z
-BX_KEY_Z+BX_KEY_SHIFT_L 'Y' SDLK_y
-BX_KEY_Z+BX_KEY_ALT_R '«' SDLK_y
-BX_KEY_Z 'y' SDLK_y
-BX_KEY_F1 none SDLK_F1
-BX_KEY_F2 none SDLK_F2
-BX_KEY_F3 none SDLK_F3
-BX_KEY_F4 none SDLK_F4
-BX_KEY_F5 none SDLK_F5
-BX_KEY_F6 none SDLK_F6
-BX_KEY_F7 none SDLK_F7
-BX_KEY_F8 none SDLK_F8
-BX_KEY_F9 none SDLK_F9
-BX_KEY_F10 none SDLK_F10
-BX_KEY_F11 none SDLK_F11
-BX_KEY_F12 none SDLK_F12
-BX_KEY_ALT_L none SDLK_LALT
-BX_KEY_ALT_L none SDLK_LMETA
-BX_KEY_ALT_R none SDLK_RALT
-BX_KEY_ALT_R none SDLK_MODE
-BX_KEY_BACKSLASH apostrophe SDLK_QUOTE
-BX_KEY_BACKSLASH '#' SDLK_HASH
-BX_KEY_BACKSPACE none SDLK_BACKSPACE
-BX_KEY_CAPS_LOCK none SDLK_CAPSLOCK
-BX_KEY_COMMA ',' SDLK_COMMA
-BX_KEY_COMMA+BX_KEY_SHIFT_L ';' SDLK_SEMICOLON
-BX_KEY_CTRL_L none SDLK_LCTRL
-BX_KEY_CTRL_R none SDLK_RCTRL
-BX_KEY_DELETE none SDLK_DELETE
-BX_KEY_DOWN none SDLK_DOWN
-BX_KEY_END none SDLK_END
-BX_KEY_ENTER return SDLK_RETURN
-BX_KEY_EQUALS none SDLK_WORLD_20
-BX_KEY_EQUALS+BX_KEY_ALT_R '¸' SDLK_WORLD_20
-BX_KEY_EQUALS+BX_KEY_SHIFT_L '`' SDLK_WORLD_20
-BX_KEY_ESC none SDLK_ESCAPE
-BX_KEY_GRAVE '^' SDLK_CARET
-BX_KEY_GRAVE+BX_KEY_SHIFT_L '°' SDLK_CARET
-BX_KEY_GRAVE+BX_KEY_ALT_R '¬' SDLK_CARET
-BX_KEY_HOME none SDLK_HOME
-BX_KEY_INSERT none SDLK_INSERT
-BX_KEY_KP_5 none SDLK_KP5
-BX_KEY_KP_ADD none SDLK_KP_PLUS
-BX_KEY_KP_DELETE none SDLK_KP_PERIOD
-BX_KEY_KP_DIVIDE none SDLK_KP_DIVIDE
-BX_KEY_KP_DOWN none SDLK_KP2
-BX_KEY_KP_END none SDLK_KP1
-BX_KEY_KP_ENTER none SDLK_KP_ENTER
-BX_KEY_KP_HOME none SDLK_KP7
-BX_KEY_KP_INSERT none SDLK_KP0
-BX_KEY_KP_LEFT none SDLK_KP4
-BX_KEY_KP_MULTIPLY none SDLK_KP_MULTIPLY
-BX_KEY_KP_PAGE_DOWN none SDLK_KP3
-BX_KEY_KP_PAGE_UP none SDLK_KP9
-BX_KEY_KP_RIGHT none SDLK_KP6
-BX_KEY_KP_SUBTRACT none SDLK_KP_MINUS
-BX_KEY_KP_UP none SDLK_KP8
-BX_KEY_LEFT none SDLK_LEFT
-BX_KEY_LEFT_BACKSLASH+BX_KEY_ALT_R '|' SDLK_LESS
-BX_KEY_LEFT_BACKSLASH+BX_KEY_SHIFT_L '>' SDLK_GREATER
-BX_KEY_LEFT_BACKSLASH '<' SDLK_LESS
-BX_KEY_LEFT_BRACKET+BX_KEY_SHIFT_L 'Ü' SDLK_WORLD_92
-BX_KEY_LEFT_BRACKET 'ü' SDLK_WORLD_92
-BX_KEY_MENU none SDLK_MENU
-BX_KEY_MINUS+BX_KEY_ALT_L backslash SDLK_BACKSLASH
-BX_KEY_MINUS+BX_KEY_SHIFT_L '?' SDLK_QUESTION
-BX_KEY_MINUS 'ß' SDLK_WORLD_63
-BX_KEY_NUM_LOCK none SDLK_NUMLOCK
-BX_KEY_PAGE_DOWN none SDLK_PAGEDOWN
-BX_KEY_PAGE_UP none SDLK_PAGEUP
-BX_KEY_PAUSE none SDLK_BREAK
-BX_KEY_PAUSE none SDLK_PAUSE
-BX_KEY_PERIOD+BX_KEY_SHIFT_L ':' SDLK_COLON
-BX_KEY_PERIOD '.' SDLK_PERIOD
-BX_KEY_PERIOD+BX_KEY_ALT_L '·' SDLK_PERIOD
-BX_KEY_PRINT none SDLK_PRINT
-BX_KEY_PRINT none SDLK_SYSREQ
-BX_KEY_RIGHT none SDLK_RIGHT
-BX_KEY_RIGHT_BRACKET+BX_KEY_ALT_R '~' SDLK_PLUS
-BX_KEY_RIGHT_BRACKET+BX_KEY_SHIFT_L '*' SDLK_PLUS
-BX_KEY_RIGHT_BRACKET '+' SDLK_PLUS
-BX_KEY_SCRL_LOCK none SDLK_SCROLLOCK
-BX_KEY_SEMICOLON+BX_KEY_SHIFT_L 'Ö' SDLK_WORLD_86
-BX_KEY_SEMICOLON 'ö' SDLK_WORLD_86
-BX_KEY_SHIFT_L none SDLK_LSHIFT
-BX_KEY_SHIFT_R none SDLK_RSHIFT
-BX_KEY_SINGLE_QUOTE+BX_KEY_SHIFT_L 'Ä' SDLK_WORLD_68
-BX_KEY_SINGLE_QUOTE 'ä' SDLK_WORLD_68
-BX_KEY_SLASH '-' SDLK_MINUS
-BX_KEY_SLASH+BX_KEY_SHIFT_L '_' SDLK_UNDERSCORE
-BX_KEY_SPACE space SDLK_SPACE
-BX_KEY_TAB tab SDLK_TAB
-BX_KEY_UP none SDLK_UP
-BX_KEY_WIN_L none SDLK_LSUPER
-BX_KEY_WIN_R none SDLK_RSUPER
+++ /dev/null
-# Bochs Keymap file
-# $Id: sdl-pc-us.map,v 1.2 2002/10/24 21:06:55 bdenney Exp $
-# Target: PC(x86) keyboard, US keymap, SDL gui
-# Author: Bryce Denney
-#
-# The keymap file describes the layout of a keyboard, and how it translates
-# into Bochs key codes.
-#
-# Format:
-# BX_Keysym ASCII_equivalent Host_key_name
-#
-# Or, for keys that require modifiers:
-# BX_Keysym+BX_Modifier ASCII_equivalent Host_key_name
-#
-# BX_Keysym and BX_Modifier must be present in the bx_key_symbol[] list in
-# gui/keymap.cc. The BX_Modifier is usually a shift key press, but it
-# could be any key. Presently a maximum of one modifier is supported, but this
-# could be changed in keymap.h (structure def has only one slot for modifier),
-# keymap.cc (parsing code), and iodev/keyboard.cc (simulate keypresses for >1
-# modifier).
-#
-# The ASCII_equivalent must be either apostrophe + one character + apostrophe,
-# or one of these keywords: space, return, tab, backslash, apostrophe, none.
-# This format is designed to look like a char constant in C, but it's a very
-# simple parser. There's no concept of backslash being an escape char. The
-# backslash and apostrophe entries are provided for aesthetic purposes only: no
-# C++ programmer wants to see '\' or '''. The parser doesn't care, but they are
-# ugly.
-#
-# Host_key_name is the name of the key combination according to the gui library
-# (X windows, SDL, etc). Each GUI module must provide a function that converts
-# these host key names into numbers. A pointer to the conversion function is
-# passed to loadKeymap(), and it is used when parsing the keymap file. As the
-# keymap file is parsed, the conversion function is called for each host key
-# name, to convert it into a number. Only the number is stored. If the host
-# key name is not found, the conversion function returns BX_KEYMAP_UNKNOWN, and
-# the keymap code will panic, like this:
-#
-# [KMAP ] line 51: unknown host key name 'SDLK_PAREN_RIGHT'
-#
-# If this happens, you must edit the keymap file, and either correct the host
-# key name or comment out that line.
-#
-
-BX_KEY_0 '0' SDLK_0
-BX_KEY_0+BX_KEY_SHIFT_L ')' SDLK_RIGHTPAREN
-BX_KEY_1 '1' SDLK_1
-BX_KEY_1+BX_KEY_SHIFT_L '!' SDLK_EXCLAIM
-BX_KEY_2 '2' SDLK_2
-BX_KEY_2+BX_KEY_SHIFT_L '@' SDLK_AT
-BX_KEY_3 '3' SDLK_3
-BX_KEY_3+BX_KEY_SHIFT_L '#' SDLK_HASH
-BX_KEY_4 '4' SDLK_4
-BX_KEY_4+BX_KEY_SHIFT_L '$' SDLK_DOLLAR
-BX_KEY_5 '5' SDLK_5
-#BX_KEY_5+BX_KEY_SHIFT_L '%' SDLK_PERCENT
-BX_KEY_6 '6' SDLK_6
-BX_KEY_6+BX_KEY_SHIFT_L '^' SDLK_CARET
-BX_KEY_7 '7' SDLK_7
-BX_KEY_7+BX_KEY_SHIFT_L '&' SDLK_AMPERSAND
-BX_KEY_8 '8' SDLK_8
-BX_KEY_8+BX_KEY_SHIFT_L '*' SDLK_ASTERISK
-BX_KEY_9 '9' SDLK_9
-BX_KEY_9+BX_KEY_SHIFT_L '(' SDLK_LEFTPAREN
-BX_KEY_A+BX_KEY_SHIFT_L 'A' SDLK_a
-BX_KEY_A 'a' SDLK_a
-BX_KEY_B+BX_KEY_SHIFT_L 'B' SDLK_b
-BX_KEY_B 'b' SDLK_b
-BX_KEY_C+BX_KEY_SHIFT_L 'C' SDLK_c
-BX_KEY_C 'c' SDLK_c
-BX_KEY_D+BX_KEY_SHIFT_L 'D' SDLK_d
-BX_KEY_D 'd' SDLK_d
-BX_KEY_E+BX_KEY_SHIFT_L 'E' SDLK_e
-BX_KEY_E 'e' SDLK_e
-BX_KEY_F+BX_KEY_SHIFT_L 'F' SDLK_f
-BX_KEY_F 'f' SDLK_f
-BX_KEY_G+BX_KEY_SHIFT_L 'G' SDLK_g
-BX_KEY_G 'g' SDLK_g
-BX_KEY_H+BX_KEY_SHIFT_L 'H' SDLK_h
-BX_KEY_H 'h' SDLK_h
-BX_KEY_I+BX_KEY_SHIFT_L 'I' SDLK_i
-BX_KEY_I 'i' SDLK_i
-BX_KEY_J+BX_KEY_SHIFT_L 'J' SDLK_j
-BX_KEY_J 'j' SDLK_j
-BX_KEY_K+BX_KEY_SHIFT_L 'K' SDLK_k
-BX_KEY_K 'k' SDLK_k
-BX_KEY_L+BX_KEY_SHIFT_L 'L' SDLK_l
-BX_KEY_L 'l' SDLK_l
-BX_KEY_M+BX_KEY_SHIFT_L 'M' SDLK_m
-BX_KEY_M 'm' SDLK_m
-BX_KEY_N+BX_KEY_SHIFT_L 'N' SDLK_n
-BX_KEY_N 'n' SDLK_n
-BX_KEY_O+BX_KEY_SHIFT_L 'O' SDLK_o
-BX_KEY_O 'o' SDLK_o
-BX_KEY_P+BX_KEY_SHIFT_L 'P' SDLK_p
-BX_KEY_P 'p' SDLK_p
-BX_KEY_Q+BX_KEY_SHIFT_L 'Q' SDLK_q
-BX_KEY_Q 'q' SDLK_q
-BX_KEY_R+BX_KEY_SHIFT_L 'R' SDLK_r
-BX_KEY_R 'r' SDLK_r
-BX_KEY_S+BX_KEY_SHIFT_L 'S' SDLK_s
-BX_KEY_S 's' SDLK_s
-BX_KEY_T+BX_KEY_SHIFT_L 'T' SDLK_t
-BX_KEY_T 't' SDLK_t
-BX_KEY_U+BX_KEY_SHIFT_L 'U' SDLK_u
-BX_KEY_U 'u' SDLK_u
-BX_KEY_V+BX_KEY_SHIFT_L 'V' SDLK_v
-BX_KEY_V 'v' SDLK_v
-BX_KEY_W+BX_KEY_SHIFT_L 'W' SDLK_w
-BX_KEY_W 'w' SDLK_w
-BX_KEY_X+BX_KEY_SHIFT_L 'X' SDLK_x
-BX_KEY_X 'x' SDLK_x
-BX_KEY_Y+BX_KEY_SHIFT_L 'Y' SDLK_y
-BX_KEY_Y 'y' SDLK_y
-BX_KEY_Z+BX_KEY_SHIFT_L 'Z' SDLK_z
-BX_KEY_Z 'z' SDLK_z
-BX_KEY_F1 none SDLK_F1
-BX_KEY_F2 none SDLK_F2
-BX_KEY_F3 none SDLK_F3
-BX_KEY_F4 none SDLK_F4
-BX_KEY_F5 none SDLK_F5
-BX_KEY_F6 none SDLK_F6
-BX_KEY_F7 none SDLK_F7
-BX_KEY_F8 none SDLK_F8
-BX_KEY_F9 none SDLK_F9
-BX_KEY_F10 none SDLK_F10
-BX_KEY_F11 none SDLK_F11
-BX_KEY_F12 none SDLK_F12
-BX_KEY_ALT_L none SDLK_LALT
-BX_KEY_ALT_L none SDLK_LMETA
-BX_KEY_ALT_R none SDLK_MODE
-#BX_KEY_ALT_R none SDLK_Multi_key
-BX_KEY_BACKSLASH backslash SDLK_BACKSLASH
-#BX_KEY_BACKSLASH+BX_KEY_SHIFT_L '|' SDLK_bar
-BX_KEY_BACKSPACE none SDLK_BACKSPACE
-BX_KEY_CAPS_LOCK none SDLK_CAPSLOCK
-BX_KEY_COMMA ',' SDLK_COMMA
-BX_KEY_COMMA+BX_KEY_SHIFT_L '<' SDLK_LESS
-BX_KEY_CTRL_L none SDLK_LCTRL
-BX_KEY_CTRL_R none SDLK_RCTRL
-BX_KEY_DELETE none SDLK_DELETE
-BX_KEY_DOWN none SDLK_DOWN
-BX_KEY_END none SDLK_END
-BX_KEY_ENTER return SDLK_RETURN
-BX_KEY_EQUALS '=' SDLK_EQUALS
-BX_KEY_EQUALS+BX_KEY_SHIFT_L '+' SDLK_PLUS
-BX_KEY_ESC none SDLK_ESCAPE
-#BX_KEY_GRAVE+BX_KEY_SHIFT_L '~' SDLK_asciitilde
-BX_KEY_GRAVE '`' SDLK_BACKQUOTE
-BX_KEY_HOME none SDLK_HOME
-BX_KEY_INSERT none SDLK_INSERT
-BX_KEY_KP_5 none SDLK_KP5
-#BX_KEY_KP_5 none SDLK_KP_BEGIN
-BX_KEY_KP_ADD none SDLK_KP_PLUS
-BX_KEY_KP_DELETE none SDLK_KP_PERIOD
-#BX_KEY_KP_DELETE none SDLK_KP_DELETE
-BX_KEY_KP_DIVIDE none SDLK_KP_DIVIDE
-BX_KEY_KP_DOWN none SDLK_KP2
-#BX_KEY_KP_DOWN none SDLK_KP_DOWN
-BX_KEY_KP_END none SDLK_KP1
-#BX_KEY_KP_END none SDLK_KP_END
-BX_KEY_KP_ENTER none SDLK_KP_ENTER
-BX_KEY_KP_HOME none SDLK_KP7
-#BX_KEY_KP_HOME none SDLK_KP_HOME
-BX_KEY_KP_INSERT none SDLK_KP0
-#BX_KEY_KP_INSERT none SDLK_KP_INSERT
-BX_KEY_KP_LEFT none SDLK_KP4
-#BX_KEY_KP_LEFT none SDLK_KP_LEFT
-BX_KEY_KP_MULTIPLY none SDLK_KP_MULTIPLY
-BX_KEY_KP_PAGE_DOWN none SDLK_KP3
-#BX_KEY_KP_PAGE_DOWN none SDLK_KP_PAGE_DOWN
-BX_KEY_KP_PAGE_UP none SDLK_KP9
-#BX_KEY_KP_PAGE_UP none SDLK_KP_PAGE_UP
-BX_KEY_KP_RIGHT none SDLK_KP6
-#BX_KEY_KP_RIGHT none SDLK_KP_Right
-BX_KEY_KP_SUBTRACT none SDLK_KP_MINUS
-BX_KEY_KP_UP none SDLK_KP8
-#BX_KEY_KP_UP none SDLK_KP_Up
-BX_KEY_LEFT none SDLK_LEFT
-#BX_KEY_LEFT_BRACKET+BX_KEY_SHIFT_L '{' SDLK_BRACELEFT
-BX_KEY_LEFT_BRACKET '[' SDLK_LEFTBRACKET
-BX_KEY_MENU none SDLK_MENU
-BX_KEY_MINUS '-' SDLK_MINUS
-BX_KEY_MINUS+BX_KEY_SHIFT_L '_' SDLK_UNDERSCORE
-BX_KEY_NUM_LOCK none SDLK_NUMLOCK
-BX_KEY_PAGE_DOWN none SDLK_PAGEDOWN
-BX_KEY_PAGE_UP none SDLK_PAGEUP
-BX_KEY_PAUSE none SDLK_BREAK
-BX_KEY_PAUSE none SDLK_PAUSE
-BX_KEY_PERIOD+BX_KEY_SHIFT_L '>' SDLK_GREATER
-BX_KEY_PERIOD '.' SDLK_PERIOD
-BX_KEY_PRINT none SDLK_PRINT
-BX_KEY_PRINT none SDLK_SYSREQ
-BX_KEY_RIGHT none SDLK_RIGHT
-#BX_KEY_RIGHT_BRACKET+BX_KEY_SHIFT_L '}' SDLK_BRACERIGHT
-BX_KEY_RIGHT_BRACKET ']' SDLK_RIGHTBRACKET
-BX_KEY_SCRL_LOCK none SDLK_SCROLLOCK
-BX_KEY_SEMICOLON+BX_KEY_SHIFT_L ':' SDLK_COLON
-BX_KEY_SEMICOLON ';' SDLK_SEMICOLON
-BX_KEY_SHIFT_L none SDLK_LSHIFT
-BX_KEY_SHIFT_R none SDLK_RSHIFT
-BX_KEY_SINGLE_QUOTE apostrophe SDLK_QUOTE
-BX_KEY_SINGLE_QUOTE+BX_KEY_SHIFT_L '"' SDLK_QUOTEDBL
-BX_KEY_SLASH+BX_KEY_SHIFT_L '?' SDLK_QUESTION
-BX_KEY_SLASH '/' SDLK_SLASH
-BX_KEY_SPACE space SDLK_SPACE
-#BX_KEY_TAB none SDLK_ISO_LEFT_TAB
-BX_KEY_TAB tab SDLK_TAB
-BX_KEY_UP none SDLK_UP
-BX_KEY_WIN_L none SDLK_LSUPER
-BX_KEY_WIN_R none SDLK_LSUPER
+++ /dev/null
-# Bochs Keymap file
-# $Id: x11-pc-be.map,v 1.2 2003/07/29 13:31:11 bdenney Exp $
-# Target: PC(x86) keyboard, BE keymap
-# Author: Wouter Verhelst,
-# based on FR keymap by Christophe Bothamy, Bryce Denney
-#
-# The keymap file describes the layout of a keyboard, and how it translates
-# into Bochs key codes.
-#
-# Format:
-# BX_Keysym ASCII_equivalent Xwin_Keysym
-#
-# Or, for keys that require modifiers:
-# BX_Keysym+BX_Modifier ASCII_equivalent Xwin_Keysym
-#
-# BX_Keysym and BX_Modifier must be present in the bx_key_symbol[] list in
-# gui/keymap.cc. The BX_Modifier is usually a shift key press, but it
-# could be any key. Presently a maximum of one modifier is supported, but this
-# could be changed in keymap.h (structure def has only one slot for modifier),
-# keymap.cc (parsing code), and iodev/keyboard.cc (simulate keypresses for >1
-# modifier).
-#
-# The ASCII_equivalent must be either apostrophe + one character + apostrophe,
-# or one of these keywords: space, return, tab, backslash, apostrophe, none.
-# This format is designed to look like a char constant in C, but it's a very
-# simple parser. There's no concept of backslash being an escape char. The
-# backslash and apostrophe entries are provided for aesthetic purposes only: no
-# C++ programmer wants to see '\' or '''. The parser doesn't care, but they are
-# ugly.
-#
-# Xwin_Keysym is the X windows equivalent of the key combination. These
-# codes should match whatever you find in /usr/X11R6/include/X11/keysymdef.h.
-# If you're running X windows, Bochs will take each of these Xwin_Keysyms,
-# pull off the XK_ in front, and use XStringToKeysym() to change them into
-# numerical codes. If this lookup fails, you will get a panic and you need
-# to edit the keymap file.
-
-BX_KEY_0+BX_KEY_SHIFT_L '0' XK_0
-BX_KEY_0 'à' XK_agrave
-BX_KEY_0+BX_KEY_ALT_R '}' XK_braceright
-BX_KEY_1+BX_KEY_SHIFT_L '1' XK_1
-BX_KEY_1 '&' XK_ampersand
-BX_KEY_1+BX_KEY_ALT_R '|' XK_bar
-BX_KEY_2+BX_KEY_SHIFT_L '2' XK_2
-BX_KEY_2+BX_KEY_ALT_R '@' XK_at
-BX_KEY_2 'é' XK_eacute
-BX_KEY_3+BX_KEY_SHIFT_L '3' XK_3
-BX_KEY_3+BX_KEY_ALT_R '#' XK_numbersign
-BX_KEY_3 '"' XK_quotedbl
-BX_KEY_4+BX_KEY_SHIFT_L '4' XK_4
-BX_KEY_4 apostrophe XK_apostrophe
-BX_KEY_5+BX_KEY_SHIFT_L '5' XK_5
-BX_KEY_5 '(' XK_parenleft
-BX_KEY_6+BX_KEY_SHIFT_L '6' XK_6
-BX_KEY_6+BX_KEY_ALT_R '^' XK_asciicircum
-BX_KEY_6 '§' XK_section
-BX_KEY_7+BX_KEY_SHIFT_L '7' XK_7
-BX_KEY_7 'è' XK_egrave
-BX_KEY_8+BX_KEY_SHIFT_L '8' XK_8
-BX_KEY_8 '!' XK_exclam
-BX_KEY_9+BX_KEY_SHIFT_L '9' XK_9
-BX_KEY_9+BX_KEY_ALT_R '{' XK_braceleft
-BX_KEY_9 'ç' XK_ccedilla
-BX_KEY_A+BX_KEY_SHIFT_L 'Q' XK_Q
-BX_KEY_A 'q' XK_q
-BX_KEY_B+BX_KEY_SHIFT_L 'B' XK_B
-BX_KEY_B 'b' XK_b
-BX_KEY_C+BX_KEY_SHIFT_L 'C' XK_C
-BX_KEY_C 'c' XK_c
-BX_KEY_D+BX_KEY_SHIFT_L 'D' XK_D
-BX_KEY_D 'd' XK_d
-BX_KEY_E+BX_KEY_SHIFT_L 'E' XK_E
-BX_KEY_E 'e' XK_e
-BX_KEY_E+BX_KEY_ALT_R none XK_EuroSign
-BX_KEY_F+BX_KEY_SHIFT_L 'F' XK_F
-BX_KEY_F 'f' XK_f
-BX_KEY_G+BX_KEY_SHIFT_L 'G' XK_G
-BX_KEY_G 'g' XK_g
-BX_KEY_H+BX_KEY_SHIFT_L 'H' XK_H
-BX_KEY_H 'h' XK_h
-BX_KEY_I+BX_KEY_SHIFT_L 'I' XK_I
-BX_KEY_I 'i' XK_i
-BX_KEY_J+BX_KEY_SHIFT_L 'J' XK_J
-BX_KEY_J 'j' XK_j
-BX_KEY_K+BX_KEY_SHIFT_L 'K' XK_K
-BX_KEY_K 'k' XK_k
-BX_KEY_L+BX_KEY_SHIFT_L 'L' XK_L
-BX_KEY_L 'l' XK_l
-BX_KEY_M+BX_KEY_SHIFT_L '?' XK_question
-BX_KEY_M ',' XK_comma
-BX_KEY_N+BX_KEY_SHIFT_L 'N' XK_N
-BX_KEY_N 'n' XK_n
-BX_KEY_O+BX_KEY_SHIFT_L 'O' XK_O
-BX_KEY_O 'o' XK_o
-BX_KEY_P+BX_KEY_SHIFT_L 'P' XK_P
-BX_KEY_P 'p' XK_p
-BX_KEY_Q+BX_KEY_SHIFT_L 'A' XK_A
-BX_KEY_Q 'a' XK_a
-BX_KEY_R+BX_KEY_SHIFT_L 'R' XK_R
-BX_KEY_R 'r' XK_r
-BX_KEY_S+BX_KEY_SHIFT_L 'S' XK_S
-BX_KEY_S 's' XK_s
-BX_KEY_T+BX_KEY_SHIFT_L 'T' XK_T
-BX_KEY_T 't' XK_t
-BX_KEY_U+BX_KEY_SHIFT_L 'U' XK_U
-BX_KEY_U 'u' XK_u
-BX_KEY_V+BX_KEY_SHIFT_L 'V' XK_V
-BX_KEY_V 'v' XK_v
-BX_KEY_W+BX_KEY_SHIFT_L 'Z' XK_Z
-BX_KEY_W 'z' XK_z
-BX_KEY_X+BX_KEY_SHIFT_L 'X' XK_X
-BX_KEY_X 'x' XK_x
-BX_KEY_Y+BX_KEY_SHIFT_L 'Y' XK_Y
-BX_KEY_Y 'y' XK_y
-BX_KEY_Z+BX_KEY_SHIFT_L 'W' XK_W
-BX_KEY_Z 'w' XK_w
-BX_KEY_F1 none XK_F1
-BX_KEY_F2 none XK_F2
-BX_KEY_F3 none XK_F3
-BX_KEY_F4 none XK_F4
-BX_KEY_F5 none XK_F5
-BX_KEY_F6 none XK_F6
-BX_KEY_F7 none XK_F7
-BX_KEY_F8 none XK_F8
-BX_KEY_F9 none XK_F9
-BX_KEY_F10 none XK_F10
-BX_KEY_F11 none XK_F11
-BX_KEY_F12 none XK_F12
-BX_KEY_ALT_L none XK_Alt_L
-BX_KEY_ALT_L none XK_Meta_L
-BX_KEY_ALT_R none XK_Alt_R
-BX_KEY_ALT_R none XK_Mode_switch
-BX_KEY_ALT_R none XK_Multi_key
-BX_KEY_BACKSLASH 'µ' XK_mu
-BX_KEY_BACKSLASH+BX_KEY_SHIFT_L '£' XK_sterling
-BX_KEY_BACKSLASH+BX_KEY_ALT_R '`' XK_dead_grave
-BX_KEY_BACKSPACE none XK_BackSpace
-BX_KEY_CAPS_LOCK none XK_Caps_Lock
-BX_KEY_COMMA+BX_KEY_SHIFT_L '.' XK_period
-BX_KEY_COMMA ';' XK_semicolon
-BX_KEY_CTRL_L none XK_Control_L
-BX_KEY_CTRL_R none XK_Control_R
-BX_KEY_DELETE none XK_Delete
-BX_KEY_DOWN none XK_Down
-BX_KEY_END none XK_End
-BX_KEY_ENTER return XK_Return
-BX_KEY_EQUALS '-' XK_minus
-BX_KEY_EQUALS+BX_KEY_SHIFT_L '_' XK_underscore
-BX_KEY_ESC none XK_Escape
-BX_KEY_GRAVE '²' XK_twosuperior
-BX_KEY_GRAVE+BX_KEY_SHIFT_L '³' XK_threesuperior
-BX_KEY_HOME none XK_Home
-BX_KEY_INSERT none XK_Insert
-BX_KEY_KP_5 none XK_KP_5
-BX_KEY_KP_5 none XK_KP_Begin
-BX_KEY_KP_ADD none XK_KP_Add
-BX_KEY_KP_DELETE none XK_KP_Decimal
-BX_KEY_KP_DELETE none XK_KP_Delete
-BX_KEY_KP_DIVIDE none XK_KP_Divide
-BX_KEY_KP_DOWN none XK_KP_2
-BX_KEY_KP_DOWN none XK_KP_Down
-BX_KEY_KP_END none XK_KP_1
-BX_KEY_KP_END none XK_KP_End
-BX_KEY_KP_ENTER none XK_KP_Enter
-BX_KEY_KP_HOME none XK_KP_7
-BX_KEY_KP_HOME none XK_KP_Home
-BX_KEY_KP_INSERT none XK_KP_0
-BX_KEY_KP_INSERT none XK_KP_Insert
-BX_KEY_KP_LEFT none XK_KP_4
-BX_KEY_KP_LEFT none XK_KP_Left
-BX_KEY_KP_MULTIPLY none XK_KP_Multiply
-BX_KEY_KP_PAGE_DOWN none XK_KP_3
-BX_KEY_KP_PAGE_DOWN none XK_KP_Page_Down
-BX_KEY_KP_PAGE_UP none XK_KP_9
-BX_KEY_KP_PAGE_UP none XK_KP_Page_Up
-BX_KEY_KP_RIGHT none XK_KP_6
-BX_KEY_KP_RIGHT none XK_KP_Right
-BX_KEY_KP_SUBTRACT none XK_KP_Subtract
-BX_KEY_KP_UP none XK_KP_8
-BX_KEY_KP_UP none XK_KP_Up
-BX_KEY_LEFT none XK_Left
-BX_KEY_LEFT_BACKSLASH+BX_KEY_SHIFT_L '>' XK_greater
-BX_KEY_LEFT_BACKSLASH '<' XK_less
-BX_KEY_LEFT_BACKSLASH+BX_KEY_ALT_R backslash XK_backslash
-BX_KEY_LEFT_BRACKET none XK_dead_circumflex
-BX_KEY_LEFT_BRACKET+BX_KEY_SHIFT_L none XK_dead_diaeresis
-BX_KEY_LEFT_BRACKET+BX_KEY_ALT_R '[' XK_bracketleft
-BX_KEY_MENU none XK_Menu
-BX_KEY_MINUS+BX_KEY_SHIFT_L '°' XK_degree
-BX_KEY_MINUS ')' XK_parenright
-BX_KEY_NUM_LOCK none XK_Num_Lock
-BX_KEY_PAGE_DOWN none XK_Page_Down
-BX_KEY_PAGE_UP none XK_Page_Up
-BX_KEY_PAUSE none XK_Break
-BX_KEY_PAUSE none XK_Pause
-BX_KEY_PERIOD ':' XK_colon
-BX_KEY_PERIOD+BX_KEY_SHIFT_L '/' XK_slash
-BX_KEY_PRINT none XK_Print
-BX_KEY_PRINT none XK_Sys_Req
-BX_KEY_RIGHT none XK_Right
-BX_KEY_RIGHT_BRACKET '$' XK_dollar
-BX_KEY_RIGHT_BRACKET+BX_KEY_SHIFT_L '*' XK_asterisk
-BX_KEY_RIGHT_BRACKET+BX_KEY_ALT_R ']' XK_bracketright
-BX_KEY_SCRL_LOCK none XK_Scroll_Lock
-BX_KEY_SEMICOLON+BX_KEY_SHIFT_L 'M' XK_M
-BX_KEY_SEMICOLON 'm' XK_m
-BX_KEY_SHIFT_L none XK_Shift_L
-BX_KEY_SHIFT_R none XK_Shift_R
-BX_KEY_SINGLE_QUOTE+BX_KEY_SHIFT_L '%' XK_percent
-BX_KEY_SINGLE_QUOTE+BX_KEY_ALT_R none XK_dead_acute
-BX_KEY_SINGLE_QUOTE 'ù' XK_ugrave
-BX_KEY_SLASH '=' XK_equal
-BX_KEY_SLASH+BX_KEY_SHIFT_L '+' XK_plus
-BX_KEY_SLASH+BX_KEY_ALT_R none XK_dead_tilde
-BX_KEY_SPACE space XK_space
-BX_KEY_TAB none XK_ISO_Left_Tab
-BX_KEY_TAB tab XK_Tab
-BX_KEY_UP none XK_Up
-BX_KEY_WIN_L none XK_Super_L
-BX_KEY_WIN_R none XK_Super_R
+++ /dev/null
-# Bochs Keymap file
-# $Id: x11-pc-da.map,v 0.9 2002/09/02
-# Target: PC(x86) keyboard, DA keymap
-# Author: Andreas Ott
-#
-# The keymap file describes the layout of a keyboard, and how it translates
-# into Bochs key codes.
-#
-# Format:
-# BX_Keysym ASCII_equivalent Xwin_Keysym
-#
-# Or, for keys that require modifiers:
-# BX_Keysym+BX_Modifier ASCII_equivalent Xwin_Keysym
-#
-# BX_Keysym and BX_Modifier must be present in the bx_key_symbol[] list in
-# gui/keymap.cc. The BX_Modifier is usually a shift key press, but it
-# could be any key. Presently a maximum of one modifier is supported, but this
-# could be changed in keymap.h (structure def has only one slot for modifier),
-# keymap.cc (parsing code), and iodev/keyboard.cc (simulate keypresses for >1
-# modifier).
-#
-# The ASCII_equivalent must be either apostrophe + one character + apostrophe,
-# or one of these keywords: space, return, tab, backslash, apostrophe, none.
-# This format is designed to look like a char constant in C, but it's a very
-# simple parser. There's no concept of backslash being an escape char. The
-# backslash and apostrophe entries are provided for aesthetic purposes only: no
-# C++ programmer wants to see '\' or '''. The parser doesn't care, but they are
-# ugly.
-#
-# Xwin_Keysym is the X windows equivalent of the key combination. These
-# codes should match whatever you find in /usr/X11R6/include/X11/keysymdef.h.
-# If you're running X windows, Bochs will take each of these Xwin_Keysyms,
-# pull off the XK_ in front, and use XStringToKeysym() to change them into
-# numerical codes. If this lookup fails, you will get a panic and you need
-# to edit the keymap file.
-
-BX_KEY_0 '0' XK_0
-BX_KEY_0+BX_KEY_ALT_R '}' XK_braceright
-BX_KEY_0+BX_KEY_SHIFT_L '=' XK_equal
-BX_KEY_1 '1' XK_1
-BX_KEY_1+BX_KEY_SHIFT_L '!' XK_exclam
-BX_KEY_1+BX_KEY_ALT_R '¡' XK_exclamdown
-BX_KEY_2 '2' XK_2
-BX_KEY_2+BX_KEY_SHIFT_L '=' XK_quotedbl
-BX_KEY_2+BX_KEY_ALT_R '@' XK_at # XK_twosuperior
-BX_KEY_3 '3' XK_3
-BX_KEY_3+BX_KEY_SHIFT_L '#' XK_numbersign
-BX_KEY_3+BX_KEY_ALT_R '£' XK_sterling
-BX_KEY_4 '4' XK_4
-BX_KEY_4+BX_KEY_SHIFT_L '¤' XK_currency
-BX_KEY_4+BX_KEY_ALT_R '$' XK_dollar
-BX_KEY_5 '5' XK_5
-BX_KEY_5+BX_KEY_ALT_R '½' XK_onehalf
-BX_KEY_5+BX_KEY_SHIFT_L '%' XK_percent
-BX_KEY_6 '6' XK_6
-BX_KEY_6+BX_KEY_SHIFT_L '&' XK_ampersand
-BX_KEY_6+BX_KEY_ALT_R '¥' XK_yen
-BX_KEY_7 '7' XK_7
-BX_KEY_7+BX_KEY_ALT_R '{' XK_braceleft
-BX_KEY_7+BX_KEY_SHIFT_L '/' XK_slash
-BX_KEY_8 '8' XK_8
-BX_KEY_8+BX_KEY_ALT_R '[' XK_bracketleft
-BX_KEY_8+BX_KEY_SHIFT_L '(' XK_parenleft
-BX_KEY_9 '9' XK_9
-BX_KEY_9+BX_KEY_ALT_R ']' XK_bracketright
-BX_KEY_9+BX_KEY_SHIFT_L ')' XK_parenright
-BX_KEY_A+BX_KEY_SHIFT_L 'A' XK_A
-BX_KEY_A 'a' XK_a
-BX_KEY_A+BX_KEY_ALT_R 'ª' XK_ordfeminine
-BX_KEY_B+BX_KEY_SHIFT_L 'B' XK_B
-BX_KEY_B 'b' XK_b
-BX_KEY_B+BX_KEY_ALT_R none XK_rightdoublequotemark
-BX_KEY_C+BX_KEY_SHIFT_L 'C' XK_C
-BX_KEY_C 'c' XK_c
-BX_KEY_C+BX_KEY_ALT_R '©' XK_copyright
-BX_KEY_D+BX_KEY_SHIFT_L 'D' XK_D
-BX_KEY_D 'd' XK_d
-BX_KEY_D+BX_KEY_ALT_R 'ð' XK_eth
-BX_KEY_E+BX_KEY_SHIFT_L 'E' XK_E
-BX_KEY_E+BX_KEY_ALT_R '?' XK_EuroSign
-BX_KEY_E 'e' XK_e
-BX_KEY_F+BX_KEY_SHIFT_L 'F' XK_F
-BX_KEY_F+BX_KEY_ALT_R '?' XK_dstroke
-BX_KEY_F 'f' XK_f
-BX_KEY_G+BX_KEY_SHIFT_L 'G' XK_G
-BX_KEY_G+BX_KEY_ALT_R '?' XK_eng
-BX_KEY_G 'g' XK_g
-BX_KEY_H+BX_KEY_SHIFT_L 'H' XK_H
-BX_KEY_H 'h' XK_h
-BX_KEY_H+BX_KEY_ALT_R '?' XK_hstroke
-BX_KEY_I+BX_KEY_SHIFT_L 'I' XK_I
-BX_KEY_I 'i' XK_i
-BX_KEY_I+BX_KEY_ALT_R none XK_rightarrow
-BX_KEY_J+BX_KEY_SHIFT_L 'J' XK_J
-BX_KEY_J 'j' XK_j
-BX_KEY_K+BX_KEY_SHIFT_L 'K' XK_K
-BX_KEY_K 'k' XK_k
-BX_KEY_K+BX_KEY_ALT_R none XK_kra
-BX_KEY_L+BX_KEY_SHIFT_L 'L' XK_L
-BX_KEY_L 'l' XK_l
-BX_KEY_M+BX_KEY_SHIFT_L 'M' XK_M
-BX_KEY_M 'm' XK_m
-BX_KEY_M+BX_KEY_ALT_R 'µ' XK_mu
-BX_KEY_N+BX_KEY_SHIFT_L 'N' XK_N
-BX_KEY_N 'n' XK_n
-BX_KEY_O+BX_KEY_SHIFT_L 'O' XK_O
-BX_KEY_O 'o' XK_o
-BX_KEY_O+BX_KEY_ALT_R none XK_oslash
-BX_KEY_P+BX_KEY_SHIFT_L 'P' XK_P
-BX_KEY_P 'p' XK_p
-BX_KEY_P+BX_KEY_ALT_R 'þ' XK_thorn
-BX_KEY_Q+BX_KEY_SHIFT_L 'Q' XK_Q
-BX_KEY_Q+BX_KEY_ALT_R '@' XK_at
-BX_KEY_Q 'q' XK_q
-BX_KEY_R+BX_KEY_SHIFT_L 'R' XK_R
-BX_KEY_R+BX_KEY_ALT_R '®' XK_registered
-BX_KEY_R 'r' XK_r
-BX_KEY_S+BX_KEY_SHIFT_L 'S' XK_S
-BX_KEY_S 's' XK_s
-BX_KEY_S+BX_KEY_ALT_R 'ß' XK_ssharp
-BX_KEY_T+BX_KEY_SHIFT_L 'T' XK_T
-BX_KEY_T 't' XK_t
-BX_KEY_T+BX_KEY_ALT_R 'þ' XK_thorn
-BX_KEY_U+BX_KEY_SHIFT_L 'U' XK_U
-BX_KEY_U+BX_KEY_ALT_R none XK_downarrow
-BX_KEY_U 'u' XK_u
-BX_KEY_V+BX_KEY_SHIFT_L 'V' XK_V
-BX_KEY_V+BX_KEY_ALT_R none XK_leftdoublequotemark
-BX_KEY_V 'v' XK_v
-BX_KEY_W+BX_KEY_SHIFT_L 'W' XK_W
-BX_KEY_W+BX_KEY_ALT_R '?' XK_lstroke
-BX_KEY_W 'w' XK_w
-BX_KEY_X+BX_KEY_SHIFT_L 'X' XK_X
-BX_KEY_X+BX_KEY_ALT_R '»' XK_guillemotright
-BX_KEY_X 'x' XK_x
-BX_KEY_Y+BX_KEY_SHIFT_L 'Y' XK_Y
-BX_KEY_Y+BX_KEY_ALT_R none XK_leftarrow
-BX_KEY_Y 'y' XK_y
-BX_KEY_Z+BX_KEY_SHIFT_L 'Z' XK_Z
-BX_KEY_Z+BX_KEY_ALT_R '«' XK_guillemotleft
-BX_KEY_Z 'z' XK_z
-BX_KEY_F1 none XK_F1
-BX_KEY_F2 none XK_F2
-BX_KEY_F3 none XK_F3
-BX_KEY_F4 none XK_F4
-BX_KEY_F5 none XK_F5
-BX_KEY_F6 none XK_F6
-BX_KEY_F7 none XK_F7
-BX_KEY_F8 none XK_F8
-BX_KEY_F9 none XK_F9
-BX_KEY_F10 none XK_F10
-BX_KEY_F11 none XK_F11
-BX_KEY_F12 none XK_F12
-BX_KEY_ALT_L none XK_Alt_L
-BX_KEY_ALT_L none XK_Meta_L
-BX_KEY_ALT_R none XK_Mode_switch
-BX_KEY_ALT_R none XK_Multi_key
-BX_KEY_BACKSLASH apostrophe XK_apostrophe
-BX_KEY_BACKSLASH+BX_KEY_SHIFT_L '*' XK_asterisk
-BX_KEY_BACKSPACE none XK_BackSpace
-BX_KEY_CAPS_LOCK none XK_Caps_Lock
-BX_KEY_COMMA ',' XK_comma
-BX_KEY_COMMA+BX_KEY_ALT_R none XK_horizconnector
-BX_KEY_COMMA+BX_KEY_SHIFT_L ';' XK_semicolon
-BX_KEY_CTRL_L none XK_Control_L
-BX_KEY_CTRL_R none XK_Control_R
-BX_KEY_DELETE none XK_Delete
-BX_KEY_DOWN none XK_Down
-BX_KEY_END none XK_End
-BX_KEY_ENTER return XK_Return
-BX_KEY_EQUALS none XK_acute
-BX_KEY_EQUALS+BX_KEY_ALT_R '|' XK_bar
-BX_KEY_EQUALS+BX_KEY_SHIFT_L '`' XK_grave
-BX_KEY_ESC none XK_Escape
-BX_KEY_GRAVE '½' XK_onehalf
-BX_KEY_GRAVE+BX_KEY_SHIFT_L '§' XK_section
-BX_KEY_GRAVE+BX_KEY_ALT_R '¾' XK_threequarters
-BX_KEY_HOME none XK_Home
-BX_KEY_INSERT none XK_Insert
-BX_KEY_KP_5 none XK_KP_5
-BX_KEY_KP_5 none XK_KP_Begin
-BX_KEY_KP_ADD none XK_KP_Add
-BX_KEY_KP_DELETE none XK_KP_Decimal
-BX_KEY_KP_DELETE none XK_KP_Delete
-BX_KEY_KP_DIVIDE none XK_KP_Divide
-BX_KEY_KP_DOWN none XK_KP_2
-BX_KEY_KP_DOWN none XK_KP_Down
-BX_KEY_KP_END none XK_KP_1
-BX_KEY_KP_END none XK_KP_End
-BX_KEY_KP_ENTER none XK_KP_Enter
-BX_KEY_KP_HOME none XK_KP_7
-BX_KEY_KP_HOME none XK_KP_Home
-BX_KEY_KP_INSERT none XK_KP_0
-BX_KEY_KP_INSERT none XK_KP_Insert
-BX_KEY_KP_LEFT none XK_KP_4
-BX_KEY_KP_LEFT none XK_KP_Left
-BX_KEY_KP_MULTIPLY none XK_KP_Multiply
-BX_KEY_KP_PAGE_DOWN none XK_KP_3
-BX_KEY_KP_PAGE_DOWN none XK_KP_Page_Down
-BX_KEY_KP_PAGE_UP none XK_KP_9
-BX_KEY_KP_PAGE_UP none XK_KP_Page_Up
-BX_KEY_KP_RIGHT none XK_KP_6
-BX_KEY_KP_RIGHT none XK_KP_Right
-BX_KEY_KP_SUBTRACT none XK_KP_Subtract
-BX_KEY_KP_UP none XK_KP_8
-BX_KEY_KP_UP none XK_KP_Up
-BX_KEY_LEFT none XK_Left
-BX_KEY_LEFT_BACKSLASH+BX_KEY_ALT_R backslash XK_backslash
-BX_KEY_LEFT_BACKSLASH+BX_KEY_SHIFT_L '>' XK_greater
-BX_KEY_LEFT_BACKSLASH '<' XK_less
-BX_KEY_LEFT_BRACKET+BX_KEY_SHIFT_L 'Å' XK_Aring
-BX_KEY_LEFT_BRACKET+BX_KEY_ALT_L none XK_diaeresis
-BX_KEY_LEFT_BRACKET 'å' XK_aring
-BX_KEY_MENU none XK_Menu
-BX_KEY_MINUS+BX_KEY_ALT_R '±' XK_plusminus
-BX_KEY_MINUS+BX_KEY_SHIFT_L '?' XK_question
-BX_KEY_MINUS '+' XK_plus
-BX_KEY_NUM_LOCK none XK_Num_Lock
-BX_KEY_PAGE_DOWN none XK_Page_Down
-BX_KEY_PAGE_UP none XK_Page_Up
-BX_KEY_PAUSE none XK_Break
-BX_KEY_PAUSE none XK_Pause
-BX_KEY_PERIOD+BX_KEY_SHIFT_L ':' XK_colon
-BX_KEY_PERIOD '.' XK_period
-BX_KEY_PERIOD+BX_KEY_ALT_R '·' XK_periodcentered
-BX_KEY_PRINT none XK_Print
-BX_KEY_PRINT none XK_Sys_Req
-BX_KEY_RIGHT none XK_Right
-BX_KEY_RIGHT_BRACKET+BX_KEY_ALT_R '~' XK_asciitilde
-BX_KEY_RIGHT_BRACKET+BX_KEY_SHIFT_L '^' XK_asciicircum
-BX_KEY_RIGHT_BRACKET '"' XK_diaeresis
-BX_KEY_SCRL_LOCK none XK_Scroll_Lock
-BX_KEY_SEMICOLON+BX_KEY_SHIFT_L 'Æ' XK_AE
-BX_KEY_SEMICOLON 'æ' XK_ae
-BX_KEY_SHIFT_L none XK_Shift_L
-BX_KEY_SHIFT_R none XK_Shift_R
-BX_KEY_SINGLE_QUOTE 'ø' XK_oslash
-BX_KEY_SINGLE_QUOTE+BX_KEY_SHIFT_L 'Ø' XK_Ooblique
-BX_KEY_SLASH+BX_KEY_ALT_R '' XK_hyphen
-BX_KEY_SLASH '-' XK_minus
-BX_KEY_SLASH+BX_KEY_SHIFT_L '_' XK_underscore
-BX_KEY_SPACE space XK_space
-BX_KEY_TAB none XK_ISO_Left_Tab
-BX_KEY_TAB tab XK_Tab
-BX_KEY_UP none XK_Up
-BX_KEY_WIN_L none XK_Super_L
-BX_KEY_WIN_R none XK_Super_R
+++ /dev/null
-# Bochs Keymap file
-# $Id: x11-pc-de.map,v 1.7 2002/10/24 21:06:56 bdenney Exp $
-# Target: PC(x86) keyboard, DE keymap
-# Author: Volker Ruppert
-#
-# The keymap file describes the layout of a keyboard, and how it translates
-# into Bochs key codes.
-#
-# Format:
-# BX_Keysym ASCII_equivalent Xwin_Keysym
-#
-# Or, for keys that require modifiers:
-# BX_Keysym+BX_Modifier ASCII_equivalent Xwin_Keysym
-#
-# BX_Keysym and BX_Modifier must be present in the bx_key_symbol[] list in
-# gui/keymap.cc. The BX_Modifier is usually a shift key press, but it
-# could be any key. Presently a maximum of one modifier is supported, but this
-# could be changed in keymap.h (structure def has only one slot for modifier),
-# keymap.cc (parsing code), and iodev/keyboard.cc (simulate keypresses for >1
-# modifier).
-#
-# The ASCII_equivalent must be either apostrophe + one character + apostrophe,
-# or one of these keywords: space, return, tab, backslash, apostrophe, none.
-# This format is designed to look like a char constant in C, but it's a very
-# simple parser. There's no concept of backslash being an escape char. The
-# backslash and apostrophe entries are provided for aesthetic purposes only: no
-# C++ programmer wants to see '\' or '''. The parser doesn't care, but they are
-# ugly.
-#
-# Xwin_Keysym is the X windows equivalent of the key combination. These
-# codes should match whatever you find in /usr/X11R6/include/X11/keysymdef.h.
-# If you're running X windows, Bochs will take each of these Xwin_Keysyms,
-# pull off the XK_ in front, and use XStringToKeysym() to change them into
-# numerical codes. If this lookup fails, you will get a panic and you need
-# to edit the keymap file.
-
-BX_KEY_0 '0' XK_0
-BX_KEY_0+BX_KEY_ALT_R '}' XK_braceright
-BX_KEY_0+BX_KEY_SHIFT_L '=' XK_equal
-BX_KEY_1 '1' XK_1
-BX_KEY_1+BX_KEY_SHIFT_L '!' XK_exclam
-BX_KEY_1+BX_KEY_ALT_R '¹' XK_onesuperior
-BX_KEY_2 '2' XK_2
-BX_KEY_2+BX_KEY_SHIFT_L '"' XK_quotedbl
-BX_KEY_2+BX_KEY_ALT_R '²' XK_twosuperior
-BX_KEY_3 '3' XK_3
-BX_KEY_3+BX_KEY_SHIFT_L '§' XK_section
-BX_KEY_3+BX_KEY_ALT_R '³' XK_threesuperior
-BX_KEY_4 '4' XK_4
-BX_KEY_4+BX_KEY_SHIFT_L '$' XK_dollar
-BX_KEY_4+BX_KEY_ALT_R '¼' XK_onequarter
-BX_KEY_5 '5' XK_5
-BX_KEY_5+BX_KEY_ALT_R '½' XK_onehalf
-BX_KEY_5+BX_KEY_SHIFT_L '%' XK_percent
-BX_KEY_6 '6' XK_6
-BX_KEY_6+BX_KEY_SHIFT_L '&' XK_ampersand
-BX_KEY_6+BX_KEY_ALT_R '¾' XK_threequarters
-BX_KEY_7 '7' XK_7
-BX_KEY_7+BX_KEY_ALT_R '{' XK_braceleft
-BX_KEY_7+BX_KEY_SHIFT_L '/' XK_slash
-BX_KEY_8 '8' XK_8
-BX_KEY_8+BX_KEY_ALT_R '[' XK_bracketleft
-BX_KEY_8+BX_KEY_SHIFT_L '(' XK_parenleft
-BX_KEY_9 '9' XK_9
-BX_KEY_9+BX_KEY_ALT_R ']' XK_bracketright
-BX_KEY_9+BX_KEY_SHIFT_L ')' XK_parenright
-BX_KEY_A+BX_KEY_SHIFT_L 'A' XK_A
-BX_KEY_A 'a' XK_a
-BX_KEY_A+BX_KEY_ALT_R 'æ' XK_ae
-BX_KEY_B+BX_KEY_SHIFT_L 'B' XK_B
-BX_KEY_B 'b' XK_b
-BX_KEY_B+BX_KEY_ALT_R none XK_rightdoublequotemark
-BX_KEY_C+BX_KEY_SHIFT_L 'C' XK_C
-BX_KEY_C 'c' XK_c
-BX_KEY_C+BX_KEY_ALT_R '¢' XK_cent
-BX_KEY_D+BX_KEY_SHIFT_L 'D' XK_D
-BX_KEY_D 'd' XK_d
-BX_KEY_D+BX_KEY_ALT_R 'ð' XK_eth
-BX_KEY_E+BX_KEY_SHIFT_L 'E' XK_E
-BX_KEY_E+BX_KEY_ALT_R none XK_EuroSign
-BX_KEY_E 'e' XK_e
-BX_KEY_F+BX_KEY_SHIFT_L 'F' XK_F
-BX_KEY_F+BX_KEY_ALT_R none XK_dstroke
-BX_KEY_F 'f' XK_f
-BX_KEY_G+BX_KEY_SHIFT_L 'G' XK_G
-BX_KEY_G+BX_KEY_ALT_R none XK_eng
-BX_KEY_G 'g' XK_g
-BX_KEY_H+BX_KEY_SHIFT_L 'H' XK_H
-BX_KEY_H 'h' XK_h
-BX_KEY_H+BX_KEY_ALT_R none XK_hstroke
-BX_KEY_I+BX_KEY_SHIFT_L 'I' XK_I
-BX_KEY_I 'i' XK_i
-BX_KEY_I+BX_KEY_ALT_R none XK_rightarrow
-BX_KEY_J+BX_KEY_SHIFT_L 'J' XK_J
-BX_KEY_J 'j' XK_j
-BX_KEY_K+BX_KEY_SHIFT_L 'K' XK_K
-BX_KEY_K 'k' XK_k
-BX_KEY_K+BX_KEY_ALT_R none XK_kra
-BX_KEY_L+BX_KEY_SHIFT_L 'L' XK_L
-BX_KEY_L 'l' XK_l
-BX_KEY_M+BX_KEY_SHIFT_L 'M' XK_M
-BX_KEY_M 'm' XK_m
-BX_KEY_M+BX_KEY_ALT_R 'µ' XK_mu
-BX_KEY_N+BX_KEY_SHIFT_L 'N' XK_N
-BX_KEY_N 'n' XK_n
-BX_KEY_O+BX_KEY_SHIFT_L 'O' XK_O
-BX_KEY_O 'o' XK_o
-BX_KEY_O+BX_KEY_ALT_R 'ø' XK_oslash
-BX_KEY_P+BX_KEY_SHIFT_L 'P' XK_P
-BX_KEY_P 'p' XK_p
-BX_KEY_P+BX_KEY_ALT_R 'þ' XK_thorn
-BX_KEY_Q+BX_KEY_SHIFT_L 'Q' XK_Q
-BX_KEY_Q+BX_KEY_ALT_R '@' XK_at
-BX_KEY_Q 'q' XK_q
-BX_KEY_R+BX_KEY_SHIFT_L 'R' XK_R
-BX_KEY_R+BX_KEY_ALT_R '¶' XK_paragraph
-BX_KEY_R 'r' XK_r
-BX_KEY_S+BX_KEY_SHIFT_L 'S' XK_S
-BX_KEY_S 's' XK_s
-BX_KEY_T+BX_KEY_SHIFT_L 'T' XK_T
-BX_KEY_T 't' XK_t
-BX_KEY_T+BX_KEY_ALT_R none XK_tslash
-BX_KEY_U+BX_KEY_SHIFT_L 'U' XK_U
-BX_KEY_U+BX_KEY_ALT_R none XK_downarrow
-BX_KEY_U 'u' XK_u
-BX_KEY_V+BX_KEY_SHIFT_L 'V' XK_V
-BX_KEY_V+BX_KEY_ALT_R none XK_leftdoublequotemark
-BX_KEY_V 'v' XK_v
-BX_KEY_W+BX_KEY_SHIFT_L 'W' XK_W
-BX_KEY_W+BX_KEY_ALT_R none XK_lstroke
-BX_KEY_W 'w' XK_w
-BX_KEY_X+BX_KEY_SHIFT_L 'X' XK_X
-BX_KEY_X+BX_KEY_ALT_R '»' XK_guillemotright
-BX_KEY_X 'x' XK_x
-BX_KEY_Y+BX_KEY_SHIFT_L 'Z' XK_Z
-BX_KEY_Y+BX_KEY_ALT_R none XK_leftarrow
-BX_KEY_Y 'z' XK_z
-BX_KEY_Z+BX_KEY_SHIFT_L 'Y' XK_Y
-BX_KEY_Z+BX_KEY_ALT_R '«' XK_guillemotleft
-BX_KEY_Z 'y' XK_y
-BX_KEY_F1 none XK_F1
-BX_KEY_F2 none XK_F2
-BX_KEY_F3 none XK_F3
-BX_KEY_F4 none XK_F4
-BX_KEY_F5 none XK_F5
-BX_KEY_F6 none XK_F6
-BX_KEY_F7 none XK_F7
-BX_KEY_F8 none XK_F8
-BX_KEY_F9 none XK_F9
-BX_KEY_F10 none XK_F10
-BX_KEY_F11 none XK_F11
-BX_KEY_F12 none XK_F12
-BX_KEY_ALT_L none XK_Alt_L
-BX_KEY_ALT_L none XK_Meta_L
-BX_KEY_ALT_R none XK_Alt_R
-BX_KEY_ALT_R none XK_Mode_switch
-BX_KEY_ALT_R none XK_Multi_key
-BX_KEY_BACKSLASH apostrophe XK_apostrophe
-BX_KEY_BACKSLASH '#' XK_numbersign
-BX_KEY_BACKSPACE none XK_BackSpace
-BX_KEY_CAPS_LOCK none XK_Caps_Lock
-BX_KEY_COMMA ',' XK_comma
-BX_KEY_COMMA+BX_KEY_ALT_R none XK_horizconnector
-BX_KEY_COMMA+BX_KEY_SHIFT_L ';' XK_semicolon
-BX_KEY_CTRL_L none XK_Control_L
-BX_KEY_CTRL_R none XK_Control_R
-BX_KEY_DELETE none XK_Delete
-BX_KEY_DOWN none XK_Down
-BX_KEY_END none XK_End
-BX_KEY_ENTER return XK_Return
-BX_KEY_EQUALS none XK_acute
-BX_KEY_EQUALS+BX_KEY_ALT_R '¸' XK_cedilla
-BX_KEY_EQUALS+BX_KEY_SHIFT_L '`' XK_grave
-BX_KEY_ESC none XK_Escape
-BX_KEY_GRAVE '^' XK_asciicircum
-BX_KEY_GRAVE+BX_KEY_SHIFT_L '°' XK_degree
-BX_KEY_GRAVE+BX_KEY_ALT_R '¬' XK_notsign
-BX_KEY_HOME none XK_Home
-BX_KEY_INSERT none XK_Insert
-BX_KEY_KP_5 none XK_KP_5
-BX_KEY_KP_5 none XK_KP_Begin
-BX_KEY_KP_ADD none XK_KP_Add
-BX_KEY_KP_DELETE none XK_KP_Decimal
-BX_KEY_KP_DELETE none XK_KP_Delete
-BX_KEY_KP_DIVIDE none XK_KP_Divide
-BX_KEY_KP_DOWN none XK_KP_2
-BX_KEY_KP_DOWN none XK_KP_Down
-BX_KEY_KP_END none XK_KP_1
-BX_KEY_KP_END none XK_KP_End
-BX_KEY_KP_ENTER none XK_KP_Enter
-BX_KEY_KP_HOME none XK_KP_7
-BX_KEY_KP_HOME none XK_KP_Home
-BX_KEY_KP_INSERT none XK_KP_0
-BX_KEY_KP_INSERT none XK_KP_Insert
-BX_KEY_KP_LEFT none XK_KP_4
-BX_KEY_KP_LEFT none XK_KP_Left
-BX_KEY_KP_MULTIPLY none XK_KP_Multiply
-BX_KEY_KP_PAGE_DOWN none XK_KP_3
-BX_KEY_KP_PAGE_DOWN none XK_KP_Page_Down
-BX_KEY_KP_PAGE_UP none XK_KP_9
-BX_KEY_KP_PAGE_UP none XK_KP_Page_Up
-BX_KEY_KP_RIGHT none XK_KP_6
-BX_KEY_KP_RIGHT none XK_KP_Right
-BX_KEY_KP_SUBTRACT none XK_KP_Subtract
-BX_KEY_KP_UP none XK_KP_8
-BX_KEY_KP_UP none XK_KP_Up
-BX_KEY_LEFT none XK_Left
-BX_KEY_LEFT_BACKSLASH+BX_KEY_ALT_R '|' XK_bar
-BX_KEY_LEFT_BACKSLASH+BX_KEY_SHIFT_L '>' XK_greater
-BX_KEY_LEFT_BACKSLASH '<' XK_less
-BX_KEY_LEFT_BRACKET+BX_KEY_SHIFT_L 'Ü' XK_Udiaeresis
-BX_KEY_LEFT_BRACKET+BX_KEY_ALT_L none XK_diaeresis
-BX_KEY_LEFT_BRACKET 'ü' XK_udiaeresis
-BX_KEY_MENU none XK_Menu
-BX_KEY_MINUS+BX_KEY_ALT_L backslash XK_backslash
-BX_KEY_MINUS+BX_KEY_SHIFT_L '?' XK_question
-BX_KEY_MINUS 'ß' XK_ssharp
-BX_KEY_NUM_LOCK none XK_Num_Lock
-BX_KEY_PAGE_DOWN none XK_Page_Down
-BX_KEY_PAGE_UP none XK_Page_Up
-BX_KEY_PAUSE none XK_Break
-BX_KEY_PAUSE none XK_Pause
-BX_KEY_PERIOD+BX_KEY_SHIFT_L ':' XK_colon
-BX_KEY_PERIOD '.' XK_period
-BX_KEY_PERIOD+BX_KEY_ALT_L '·' XK_periodcentered
-BX_KEY_PRINT none XK_Print
-BX_KEY_PRINT none XK_Sys_Req
-BX_KEY_RIGHT none XK_Right
-BX_KEY_RIGHT_BRACKET+BX_KEY_ALT_R '~' XK_asciitilde
-BX_KEY_RIGHT_BRACKET+BX_KEY_SHIFT_L '*' XK_asterisk
-BX_KEY_RIGHT_BRACKET '+' XK_plus
-BX_KEY_SCRL_LOCK none XK_Scroll_Lock
-BX_KEY_SEMICOLON+BX_KEY_SHIFT_L 'Ö' XK_Odiaeresis
-BX_KEY_SEMICOLON 'ö' XK_odiaeresis
-BX_KEY_SHIFT_L none XK_Shift_L
-BX_KEY_SHIFT_R none XK_Shift_R
-BX_KEY_SINGLE_QUOTE+BX_KEY_SHIFT_L 'Ä' XK_Adiaeresis
-BX_KEY_SINGLE_QUOTE 'ä' XK_adiaeresis
-BX_KEY_SLASH none XK_dead_belowdot
-BX_KEY_SLASH '-' XK_minus
-BX_KEY_SLASH+BX_KEY_SHIFT_L '_' XK_underscore
-BX_KEY_SPACE space XK_space
-BX_KEY_TAB none XK_ISO_Left_Tab
-BX_KEY_TAB tab XK_Tab
-BX_KEY_UP none XK_Up
-BX_KEY_WIN_L none XK_Super_L
-BX_KEY_WIN_R none XK_Super_R
+++ /dev/null
-# Bochs Keymap file
-# $Id: x11-pc-es.map,v 1.4 2002/09/25 08:00:24 bdenney Exp $
-# Target: PC(x86) keyboard, ES keymap
-# Author: Vicente Hernando Ara
-#
-# The keymap file describes the layout of a keyboard, and how it translates
-# into Bochs key codes.
-#
-# Format:
-# BX_Keysym ASCII_equivalent Xwin_Keysym
-#
-# Or, for keys that require modifiers:
-# BX_Keysym+BX_Modifier ASCII_equivalent Xwin_Keysym
-#
-# BX_Keysym and BX_Modifier must be present in the bx_key_symbol[] list in
-# gui/keymap.cc. The BX_Modifier is usually a shift key press, but it
-# could be any key. Presently a maximum of one modifier is supported, but this
-# could be changed in keymap.h (structure def has only one slot for modifier),
-# keymap.cc (parsing code), and iodev/keyboard.cc (simulate keypresses for >1
-# modifier).
-#
-# The ASCII_equivalent must be either apostrophe + one character + apostrophe,
-# or one of these keywords: space, return, tab, backslash, apostrophe, none.
-# This format is designed to look like a char constant in C, but it's a very
-# simple parser. There's no concept of backslash being an escape char. The
-# backslash and apostrophe entries are provided for aesthetic purposes only: no
-# C++ programmer wants to see '\' or '''. The parser doesn't care, but they are
-# ugly.
-#
-# Xwin_Keysym is the X windows equivalent of the key combination. These
-# codes should match whatever you find in /usr/X11R6/include/X11/keysymdef.h.
-# If you're running X windows, Bochs will take each of these Xwin_Keysyms,
-# pull off the XK_ in front, and use XStringToKeysym() to change them into
-# numerical codes. If this lookup fails, you will get a panic and you need
-# to edit the keymap file.
-#
-BX_KEY_0 none XK_0
-BX_KEY_0 none XK_equal
-BX_KEY_1 none XK_1
-BX_KEY_1 none XK_bar
-BX_KEY_1 none XK_exclam
-BX_KEY_2 none XK_2
-BX_KEY_2 none XK_at
-BX_KEY_2 none XK_quotedbl
-BX_KEY_3 none XK_3
-BX_KEY_3 none XK_numbersign
-BX_KEY_3 none XK_periodcentered
-BX_KEY_4 none XK_4
-BX_KEY_4 none XK_dollar
-BX_KEY_5 none XK_5
-BX_KEY_5 none XK_percent
-BX_KEY_6 none XK_6
-BX_KEY_6 none XK_ampersand
-BX_KEY_7 none XK_7
-BX_KEY_7 none XK_slash
-BX_KEY_8 none XK_8
-BX_KEY_8 none XK_parenleft
-BX_KEY_9 none XK_9
-BX_KEY_9 none XK_parenright
-BX_KEY_A none XK_A
-BX_KEY_A none XK_a
-BX_KEY_B none XK_B
-BX_KEY_B none XK_b
-BX_KEY_C none XK_C
-BX_KEY_C none XK_c
-BX_KEY_D none XK_D
-BX_KEY_D none XK_d
-BX_KEY_E none XK_E
-BX_KEY_E none XK_EuroSign
-BX_KEY_E none XK_e
-BX_KEY_F none XK_F
-BX_KEY_F none XK_f
-BX_KEY_G none XK_G
-BX_KEY_G none XK_g
-BX_KEY_H none XK_H
-BX_KEY_H none XK_h
-BX_KEY_I none XK_I
-BX_KEY_I none XK_i
-BX_KEY_J none XK_J
-BX_KEY_J none XK_j
-BX_KEY_K none XK_K
-BX_KEY_K none XK_k
-BX_KEY_L none XK_L
-BX_KEY_L none XK_l
-BX_KEY_M none XK_M
-BX_KEY_M none XK_m
-BX_KEY_N none XK_N
-BX_KEY_N none XK_n
-BX_KEY_O none XK_O
-BX_KEY_O none XK_o
-BX_KEY_P none XK_P
-BX_KEY_P none XK_p
-BX_KEY_Q none XK_Q
-BX_KEY_Q none XK_q
-BX_KEY_R none XK_R
-BX_KEY_R none XK_r
-BX_KEY_S none XK_S
-BX_KEY_S none XK_s
-BX_KEY_T none XK_T
-BX_KEY_T none XK_t
-BX_KEY_U none XK_U
-BX_KEY_U none XK_u
-BX_KEY_V none XK_V
-BX_KEY_V none XK_v
-BX_KEY_W none XK_W
-BX_KEY_W none XK_w
-BX_KEY_X none XK_X
-BX_KEY_X none XK_x
-BX_KEY_Y none XK_Y
-BX_KEY_Y none XK_y
-BX_KEY_Z none XK_Z
-BX_KEY_Z none XK_z
-BX_KEY_F1 none XK_F1
-BX_KEY_F2 none XK_F2
-BX_KEY_F3 none XK_F3
-BX_KEY_F4 none XK_F4
-BX_KEY_F5 none XK_F5
-BX_KEY_F6 none XK_F6
-BX_KEY_F7 none XK_F7
-BX_KEY_F8 none XK_F8
-BX_KEY_F9 none XK_F9
-BX_KEY_F10 none XK_F10
-BX_KEY_F11 none XK_F11
-BX_KEY_F12 none XK_F12
-BX_KEY_ALT_L none XK_Alt_L
-BX_KEY_ALT_L none XK_Meta_L
-BX_KEY_ALT_R none XK_Alt_R
-BX_KEY_ALT_R none XK_Mode_switch
-BX_KEY_ALT_R none XK_Multi_key
-BX_KEY_BACKSLASH none XK_Ccedilla
-BX_KEY_BACKSLASH none XK_ccedilla
-BX_KEY_BACKSPACE none XK_BackSpace
-BX_KEY_CAPS_LOCK none XK_Caps_Lock
-BX_KEY_COMMA none XK_comma
-BX_KEY_COMMA none XK_semicolon
-BX_KEY_CTRL_L none XK_Control_L
-BX_KEY_CTRL_R none XK_Control_R
-BX_KEY_DELETE none XK_Delete
-BX_KEY_DOWN none XK_Down
-BX_KEY_END none XK_End
-BX_KEY_ENTER none XK_Return
-BX_KEY_EQUALS none XK_exclamdown
-BX_KEY_EQUALS none XK_questiondown
-BX_KEY_ESC none XK_Escape
-BX_KEY_GRAVE none XK_asciitilde
-BX_KEY_GRAVE none XK_backslash
-BX_KEY_GRAVE none XK_grave
-BX_KEY_GRAVE none XK_masculine
-BX_KEY_GRAVE none XK_ordfeminine
-BX_KEY_HOME none XK_Home
-BX_KEY_INSERT none XK_Insert
-BX_KEY_KP_5 none XK_KP_5
-BX_KEY_KP_5 none XK_KP_Begin
-BX_KEY_KP_ADD none XK_KP_Add
-BX_KEY_KP_DELETE none XK_KP_Decimal
-BX_KEY_KP_DELETE none XK_KP_Delete
-BX_KEY_KP_DIVIDE none XK_KP_Divide
-BX_KEY_KP_DOWN none XK_KP_2
-BX_KEY_KP_DOWN none XK_KP_Down
-BX_KEY_KP_END none XK_KP_1
-BX_KEY_KP_END none XK_KP_End
-BX_KEY_KP_ENTER none XK_KP_Enter
-BX_KEY_KP_HOME none XK_KP_7
-BX_KEY_KP_HOME none XK_KP_Home
-BX_KEY_KP_INSERT none XK_KP_0
-BX_KEY_KP_INSERT none XK_KP_Insert
-BX_KEY_KP_LEFT none XK_KP_4
-BX_KEY_KP_LEFT none XK_KP_Left
-BX_KEY_KP_MULTIPLY none XK_KP_Multiply
-BX_KEY_KP_PAGE_DOWN none XK_KP_3
-BX_KEY_KP_PAGE_DOWN none XK_KP_Page_Down
-BX_KEY_KP_PAGE_UP none XK_KP_9
-BX_KEY_KP_PAGE_UP none XK_KP_Page_Up
-BX_KEY_KP_RIGHT none XK_KP_6
-BX_KEY_KP_RIGHT none XK_KP_Right
-BX_KEY_KP_SUBTRACT none XK_KP_Subtract
-BX_KEY_KP_UP none XK_KP_8
-BX_KEY_KP_UP none XK_KP_Up
-BX_KEY_LEFT none XK_Left
-BX_KEY_LEFT_BACKSLASH none XK_greater
-BX_KEY_LEFT_BACKSLASH none XK_less
-BX_KEY_LEFT_BRACKET none XK_braceleft
-BX_KEY_LEFT_BRACKET none XK_bracketleft
-BX_KEY_LEFT_BRACKET none XK_dead_circumflex
-BX_KEY_LEFT_BRACKET none XK_dead_grave
-BX_KEY_MENU none XK_Menu
-BX_KEY_MINUS none XK_apostrophe
-BX_KEY_MINUS none XK_question
-BX_KEY_NUM_LOCK none XK_Num_Lock
-BX_KEY_PAGE_DOWN none XK_Page_Down
-BX_KEY_PAGE_UP none XK_Page_Up
-BX_KEY_PAUSE none XK_Break
-BX_KEY_PAUSE none XK_Pause
-BX_KEY_PERIOD none XK_colon
-BX_KEY_PERIOD none XK_period
-BX_KEY_PRINT none XK_Print
-BX_KEY_PRINT none XK_Sys_Req
-BX_KEY_RIGHT none XK_Right
-BX_KEY_RIGHT_BRACKET none XK_asterisk
-BX_KEY_RIGHT_BRACKET none XK_braceright
-BX_KEY_RIGHT_BRACKET none XK_bracketright
-BX_KEY_RIGHT_BRACKET none XK_plus
-BX_KEY_SCRL_LOCK none XK_Scroll_Lock
-BX_KEY_SEMICOLON none XK_Ntilde
-BX_KEY_SEMICOLON none XK_ntilde
-BX_KEY_SHIFT_L none XK_Shift_L
-BX_KEY_SHIFT_R none XK_Shift_R
-BX_KEY_SINGLE_QUOTE none XK_dead_acute
-BX_KEY_SINGLE_QUOTE none XK_dead_diaeresis
-BX_KEY_SLASH none XK_minus
-BX_KEY_SLASH none XK_underscore
-BX_KEY_SPACE none XK_space
-BX_KEY_TAB none XK_ISO_Left_Tab
-BX_KEY_TAB none XK_Tab
-BX_KEY_UP none XK_Up
-BX_KEY_WIN_L none XK_Super_L
-BX_KEY_WIN_R none XK_Super_R
+++ /dev/null
-# Bochs Keymap file
-# $Id: x11-pc-fr.map,v 1.5 2002/09/25 08:00:24 bdenney Exp $
-# Target: PC(x86) keyboard, FR keymap
-# Author: Christophe Bothamy, Bryce Denney
-#
-# The keymap file describes the layout of a keyboard, and how it translates
-# into Bochs key codes.
-#
-# Format:
-# BX_Keysym ASCII_equivalent Xwin_Keysym
-#
-# Or, for keys that require modifiers:
-# BX_Keysym+BX_Modifier ASCII_equivalent Xwin_Keysym
-#
-# BX_Keysym and BX_Modifier must be present in the bx_key_symbol[] list in
-# gui/keymap.cc. The BX_Modifier is usually a shift key press, but it
-# could be any key. Presently a maximum of one modifier is supported, but this
-# could be changed in keymap.h (structure def has only one slot for modifier),
-# keymap.cc (parsing code), and iodev/keyboard.cc (simulate keypresses for >1
-# modifier).
-#
-# The ASCII_equivalent must be either apostrophe + one character + apostrophe,
-# or one of these keywords: space, return, tab, backslash, apostrophe, none.
-# This format is designed to look like a char constant in C, but it's a very
-# simple parser. There's no concept of backslash being an escape char. The
-# backslash and apostrophe entries are provided for aesthetic purposes only: no
-# C++ programmer wants to see '\' or '''. The parser doesn't care, but they are
-# ugly.
-#
-# Xwin_Keysym is the X windows equivalent of the key combination. These
-# codes should match whatever you find in /usr/X11R6/include/X11/keysymdef.h.
-# If you're running X windows, Bochs will take each of these Xwin_Keysyms,
-# pull off the XK_ in front, and use XStringToKeysym() to change them into
-# numerical codes. If this lookup fails, you will get a panic and you need
-# to edit the keymap file.
-
-BX_KEY_0+BX_KEY_SHIFT_L '0' XK_0
-BX_KEY_0 'à' XK_agrave
-BX_KEY_0+BX_KEY_ALT_R '@' XK_at
-BX_KEY_1+BX_KEY_SHIFT_L '1' XK_1
-BX_KEY_1 '&' XK_ampersand
-BX_KEY_2+BX_KEY_SHIFT_L '2' XK_2
-BX_KEY_2+BX_KEY_ALT_R '~' XK_asciitilde
-BX_KEY_2 'é' XK_eacute
-BX_KEY_3+BX_KEY_SHIFT_L '3' XK_3
-BX_KEY_3+BX_KEY_ALT_R '#' XK_numbersign
-BX_KEY_3 '"' XK_quotedbl
-BX_KEY_4+BX_KEY_SHIFT_L '4' XK_4
-BX_KEY_4 apostrophe XK_apostrophe
-BX_KEY_4+BX_KEY_ALT_R '{' XK_braceleft
-BX_KEY_5+BX_KEY_SHIFT_L '5' XK_5
-BX_KEY_5+BX_KEY_ALT_R '[' XK_bracketleft
-BX_KEY_5 '(' XK_parenleft
-BX_KEY_6+BX_KEY_SHIFT_L '6' XK_6
-BX_KEY_6+BX_KEY_ALT_R '|' XK_bar
-BX_KEY_6 '-' XK_minus
-BX_KEY_7+BX_KEY_SHIFT_L '7' XK_7
-BX_KEY_7 'è' XK_egrave
-BX_KEY_7+BX_KEY_ALT_R '`' XK_grave
-BX_KEY_8+BX_KEY_SHIFT_L '8' XK_8
-BX_KEY_8+BX_KEY_ALT_R backslash XK_backslash
-BX_KEY_8 '_' XK_underscore
-BX_KEY_9+BX_KEY_SHIFT_L '9' XK_9
-BX_KEY_9+BX_KEY_ALT_R '^' XK_asciicircum
-BX_KEY_9 'ç' XK_ccedilla
-BX_KEY_A+BX_KEY_SHIFT_L 'Q' XK_Q
-BX_KEY_A 'q' XK_q
-BX_KEY_B+BX_KEY_SHIFT_L 'B' XK_B
-BX_KEY_B 'b' XK_b
-BX_KEY_C+BX_KEY_SHIFT_L 'C' XK_C
-BX_KEY_C 'c' XK_c
-BX_KEY_D+BX_KEY_SHIFT_L 'D' XK_D
-BX_KEY_D 'd' XK_d
-BX_KEY_E+BX_KEY_SHIFT_L 'E' XK_E
-BX_KEY_E 'e' XK_e
-BX_KEY_E+BX_KEY_ALT_R none XK_EuroSign
-BX_KEY_F+BX_KEY_SHIFT_L 'F' XK_F
-BX_KEY_F 'f' XK_f
-BX_KEY_G+BX_KEY_SHIFT_L 'G' XK_G
-BX_KEY_G 'g' XK_g
-BX_KEY_H+BX_KEY_SHIFT_L 'H' XK_H
-BX_KEY_H 'h' XK_h
-BX_KEY_I+BX_KEY_SHIFT_L 'I' XK_I
-BX_KEY_I 'i' XK_i
-BX_KEY_J+BX_KEY_SHIFT_L 'J' XK_J
-BX_KEY_J 'j' XK_j
-BX_KEY_K+BX_KEY_SHIFT_L 'K' XK_K
-BX_KEY_K 'k' XK_k
-BX_KEY_L+BX_KEY_SHIFT_L 'L' XK_L
-BX_KEY_L 'l' XK_l
-BX_KEY_M+BX_KEY_SHIFT_L '?' XK_question
-BX_KEY_M ',' XK_comma
-BX_KEY_N+BX_KEY_SHIFT_L 'N' XK_N
-BX_KEY_N 'n' XK_n
-BX_KEY_O+BX_KEY_SHIFT_L 'O' XK_O
-BX_KEY_O 'o' XK_o
-BX_KEY_P+BX_KEY_SHIFT_L 'P' XK_P
-BX_KEY_P 'p' XK_p
-BX_KEY_Q+BX_KEY_SHIFT_L 'A' XK_A
-BX_KEY_Q 'a' XK_a
-BX_KEY_R+BX_KEY_SHIFT_L 'R' XK_R
-BX_KEY_R 'r' XK_r
-BX_KEY_S+BX_KEY_SHIFT_L 'S' XK_S
-BX_KEY_S 's' XK_s
-BX_KEY_T+BX_KEY_SHIFT_L 'T' XK_T
-BX_KEY_T 't' XK_t
-BX_KEY_U+BX_KEY_SHIFT_L 'U' XK_U
-BX_KEY_U 'u' XK_u
-BX_KEY_V+BX_KEY_SHIFT_L 'V' XK_V
-BX_KEY_V 'v' XK_v
-BX_KEY_W+BX_KEY_SHIFT_L 'Z' XK_Z
-BX_KEY_W 'z' XK_z
-BX_KEY_X+BX_KEY_SHIFT_L 'X' XK_X
-BX_KEY_X 'x' XK_x
-BX_KEY_Y+BX_KEY_SHIFT_L 'Y' XK_Y
-BX_KEY_Y 'y' XK_y
-BX_KEY_Z+BX_KEY_SHIFT_L 'W' XK_W
-BX_KEY_Z 'w' XK_w
-BX_KEY_F1 none XK_F1
-BX_KEY_F2 none XK_F2
-BX_KEY_F3 none XK_F3
-BX_KEY_F4 none XK_F4
-BX_KEY_F5 none XK_F5
-BX_KEY_F6 none XK_F6
-BX_KEY_F7 none XK_F7
-BX_KEY_F8 none XK_F8
-BX_KEY_F9 none XK_F9
-BX_KEY_F10 none XK_F10
-BX_KEY_F11 none XK_F11
-BX_KEY_F12 none XK_F12
-BX_KEY_ALT_L none XK_Alt_L
-BX_KEY_ALT_L none XK_Meta_L
-BX_KEY_ALT_R none XK_Alt_R
-BX_KEY_ALT_R none XK_Mode_switch
-BX_KEY_ALT_R none XK_Multi_key
-BX_KEY_BACKSLASH '*' XK_asterisk
-BX_KEY_BACKSLASH+BX_KEY_SHIFT_L 'µ' XK_mu
-BX_KEY_BACKSPACE none XK_BackSpace
-BX_KEY_CAPS_LOCK none XK_Caps_Lock
-BX_KEY_COMMA+BX_KEY_SHIFT_L '.' XK_period
-BX_KEY_COMMA ';' XK_semicolon
-BX_KEY_CTRL_L none XK_Control_L
-BX_KEY_CTRL_R none XK_Control_R
-BX_KEY_DELETE none XK_Delete
-BX_KEY_DOWN none XK_Down
-BX_KEY_END none XK_End
-BX_KEY_ENTER return XK_Return
-BX_KEY_EQUALS+BX_KEY_ALT_R '}' XK_braceright
-BX_KEY_EQUALS '=' XK_equal
-BX_KEY_EQUALS+BX_KEY_SHIFT_L '+' XK_plus
-BX_KEY_ESC none XK_Escape
-BX_KEY_GRAVE '²' XK_twosuperior
-BX_KEY_HOME none XK_Home
-BX_KEY_INSERT none XK_Insert
-BX_KEY_KP_5 none XK_KP_5
-BX_KEY_KP_5 none XK_KP_Begin
-BX_KEY_KP_ADD none XK_KP_Add
-BX_KEY_KP_DELETE none XK_KP_Decimal
-BX_KEY_KP_DELETE none XK_KP_Delete
-BX_KEY_KP_DIVIDE none XK_KP_Divide
-BX_KEY_KP_DOWN none XK_KP_2
-BX_KEY_KP_DOWN none XK_KP_Down
-BX_KEY_KP_END none XK_KP_1
-BX_KEY_KP_END none XK_KP_End
-BX_KEY_KP_ENTER none XK_KP_Enter
-BX_KEY_KP_HOME none XK_KP_7
-BX_KEY_KP_HOME none XK_KP_Home
-BX_KEY_KP_INSERT none XK_KP_0
-BX_KEY_KP_INSERT none XK_KP_Insert
-BX_KEY_KP_LEFT none XK_KP_4
-BX_KEY_KP_LEFT none XK_KP_Left
-BX_KEY_KP_MULTIPLY none XK_KP_Multiply
-BX_KEY_KP_PAGE_DOWN none XK_KP_3
-BX_KEY_KP_PAGE_DOWN none XK_KP_Page_Down
-BX_KEY_KP_PAGE_UP none XK_KP_9
-BX_KEY_KP_PAGE_UP none XK_KP_Page_Up
-BX_KEY_KP_RIGHT none XK_KP_6
-BX_KEY_KP_RIGHT none XK_KP_Right
-BX_KEY_KP_SUBTRACT none XK_KP_Subtract
-BX_KEY_KP_UP none XK_KP_8
-BX_KEY_KP_UP none XK_KP_Up
-BX_KEY_LEFT none XK_Left
-BX_KEY_LEFT_BACKSLASH+BX_KEY_SHIFT_L '>' XK_greater
-BX_KEY_LEFT_BACKSLASH '<' XK_less
-BX_KEY_LEFT_BRACKET '^' XK_dead_circumflex
-BX_KEY_LEFT_BRACKET none XK_dead_diaeresis
-BX_KEY_MENU none XK_Menu
-BX_KEY_MINUS+BX_KEY_ALT_R ']' XK_bracketright
-BX_KEY_MINUS+BX_KEY_SHIFT_L '°' XK_degree
-BX_KEY_MINUS ')' XK_parenright
-BX_KEY_NUM_LOCK none XK_Num_Lock
-BX_KEY_PAGE_DOWN none XK_Page_Down
-BX_KEY_PAGE_UP none XK_Page_Up
-BX_KEY_PAUSE none XK_Break
-BX_KEY_PAUSE none XK_Pause
-BX_KEY_PERIOD ':' XK_colon
-BX_KEY_PERIOD+BX_KEY_SHIFT_L '/' XK_slash
-BX_KEY_PRINT none XK_Print
-BX_KEY_PRINT none XK_Sys_Req
-BX_KEY_RIGHT none XK_Right
-BX_KEY_RIGHT_BRACKET+BX_KEY_ALT_R '¤' XK_currency
-BX_KEY_RIGHT_BRACKET '$' XK_dollar
-BX_KEY_RIGHT_BRACKET+BX_KEY_SHIFT_L '£' XK_sterling
-BX_KEY_SCRL_LOCK none XK_Scroll_Lock
-BX_KEY_SEMICOLON+BX_KEY_SHIFT_L 'M' XK_M
-BX_KEY_SEMICOLON 'm' XK_m
-BX_KEY_SHIFT_L none XK_Shift_L
-BX_KEY_SHIFT_R none XK_Shift_R
-BX_KEY_SINGLE_QUOTE+BX_KEY_SHIFT_L '%' XK_percent
-BX_KEY_SINGLE_QUOTE 'ù' XK_ugrave
-BX_KEY_SLASH '!' XK_exclam
-BX_KEY_SLASH+BX_KEY_SHIFT_L '§' XK_section
-BX_KEY_SPACE space XK_space
-BX_KEY_TAB none XK_ISO_Left_Tab
-BX_KEY_TAB tab XK_Tab
-BX_KEY_UP none XK_Up
-BX_KEY_WIN_L none XK_Super_L
-BX_KEY_WIN_R none XK_Super_R
+++ /dev/null
-# Bochs Keymap file
-# $Id: x11-pc-it.map,v 1.2 2002/09/25 08:00:25 bdenney Exp $
-# Target: PC(x86) keyboard, IT keymap
-# Author: Emanuele Goldoni
-#
-# The keymap file describes the layout of a keyboard, and how it translates
-# into Bochs key codes.
-#
-# Format:
-# BX_Keysym ASCII_equivalent Xwin_Keysym
-#
-# Or, for keys that require modifiers:
-# BX_Keysym+BX_Modifier ASCII_equivalent Xwin_Keysym
-#
-# BX_Keysym and BX_Modifier must be present in the bx_key_symbol[] list in
-# gui/keymap.cc. The BX_Modifier is usually a shift key press, but it
-# could be any key. Presently a maximum of one modifier is supported, but this
-# could be changed in keymap.h (structure def has only one slot for modifier),
-# keymap.cc (parsing code), and iodev/keyboard.cc (simulate keypresses for >1
-# modifier).
-#
-# The ASCII_equivalent must be either apostrophe + one character + apostrophe,
-# or one of these keywords: space, return, tab, backslash, apostrophe, none.
-# This format is designed to look like a char constant in C, but it's a very
-# simple parser. There's no concept of backslash being an escape char. The
-# backslash and apostrophe entries are provided for aesthetic purposes only: no
-# C++ programmer wants to see '\' or '''. The parser doesn't care, but they are
-# ugly.
-#
-# Xwin_Keysym is the X windows equivalent of the key combination. These
-# codes should match whatever you find in /usr/X11R6/include/X11/keysymdef.h.
-# If you're running X windows, Bochs will take each of these Xwin_Keysyms,
-# pull off the XK_ in front, and use XStringToKeysym() to change them into
-# numerical codes. If this lookup fails, you will get a panic and you need
-# to edit the keymap file.
-#
-
-BX_KEY_0 '0' XK_0
-BX_KEY_0+BX_KEY_SHIFT_L '=' XK_equal
-BX_KEY_1 '1' XK_1
-BX_KEY_1+BX_KEY_SHIFT_L '!' XK_exclam
-BX_KEY_2 '2' XK_2
-BX_KEY_2+BX_KEY_SHIFT_L '"' XK_quotedbl
-BX_KEY_3 '3' XK_3
-BX_KEY_3+BX_KEY_SHIFT_L '£' XK_sterling
-BX_KEY_4 '4' XK_4
-BX_KEY_4+BX_KEY_SHIFT_L '$' XK_dollar
-BX_KEY_5 '5' XK_5
-BX_KEY_5+BX_KEY_SHIFT_L '%' XK_percent
-BX_KEY_6 '6' XK_6
-BX_KEY_6+BX_KEY_SHIFT_L '&' XK_ampersand
-BX_KEY_7 '7' XK_7
-BX_KEY_7+BX_KEY_SHIFT_L '/' XK_slash
-BX_KEY_8 '8' XK_8
-BX_KEY_8+BX_KEY_SHIFT_L '(' XK_parenleft
-BX_KEY_9 '9' XK_9
-BX_KEY_9+BX_KEY_SHIFT_L ')' XK_parenright
-BX_KEY_A+BX_KEY_SHIFT_L 'A' XK_A
-BX_KEY_A 'a' XK_a
-BX_KEY_B+BX_KEY_SHIFT_L 'B' XK_B
-BX_KEY_B 'b' XK_b
-BX_KEY_C+BX_KEY_SHIFT_L 'C' XK_C
-BX_KEY_C 'c' XK_c
-BX_KEY_D+BX_KEY_SHIFT_L 'D' XK_D
-BX_KEY_D 'd' XK_d
-BX_KEY_E+BX_KEY_SHIFT_L 'E' XK_E
-BX_KEY_E 'e' XK_e
-BX_KEY_F+BX_KEY_SHIFT_L 'F' XK_F
-BX_KEY_F 'f' XK_f
-BX_KEY_G+BX_KEY_SHIFT_L 'G' XK_G
-BX_KEY_G 'g' XK_g
-BX_KEY_H+BX_KEY_SHIFT_L 'H' XK_H
-BX_KEY_H 'h' XK_h
-BX_KEY_I+BX_KEY_SHIFT_L 'I' XK_I
-BX_KEY_I 'i' XK_i
-BX_KEY_J+BX_KEY_SHIFT_L 'J' XK_J
-BX_KEY_J 'j' XK_j
-BX_KEY_K+BX_KEY_SHIFT_L 'K' XK_K
-BX_KEY_K 'k' XK_k
-BX_KEY_L+BX_KEY_SHIFT_L 'L' XK_L
-BX_KEY_L 'l' XK_l
-BX_KEY_M+BX_KEY_SHIFT_L 'M' XK_M
-BX_KEY_M 'm' XK_m
-BX_KEY_N+BX_KEY_SHIFT_L 'N' XK_N
-BX_KEY_N 'n' XK_n
-BX_KEY_O+BX_KEY_SHIFT_L 'O' XK_O
-BX_KEY_O 'o' XK_o
-BX_KEY_P+BX_KEY_SHIFT_L 'P' XK_P
-BX_KEY_P 'p' XK_p
-BX_KEY_Q+BX_KEY_SHIFT_L 'Q' XK_Q
-BX_KEY_Q 'q' XK_q
-BX_KEY_R+BX_KEY_SHIFT_L 'R' XK_R
-BX_KEY_R 'r' XK_r
-BX_KEY_S+BX_KEY_SHIFT_L 'S' XK_S
-BX_KEY_S 's' XK_s
-BX_KEY_T+BX_KEY_SHIFT_L 'T' XK_T
-BX_KEY_T 't' XK_t
-BX_KEY_U+BX_KEY_SHIFT_L 'U' XK_U
-BX_KEY_U 'u' XK_u
-BX_KEY_V+BX_KEY_SHIFT_L 'V' XK_V
-BX_KEY_V 'v' XK_v
-BX_KEY_W+BX_KEY_SHIFT_L 'W' XK_W
-BX_KEY_W 'w' XK_w
-BX_KEY_X+BX_KEY_SHIFT_L 'X' XK_X
-BX_KEY_X 'x' XK_x
-BX_KEY_Y+BX_KEY_SHIFT_L 'Y' XK_Y
-BX_KEY_Y 'y' XK_y
-BX_KEY_Z+BX_KEY_SHIFT_L 'Z' XK_Z
-BX_KEY_Z 'z' XK_z
-BX_KEY_F1 none XK_F1
-BX_KEY_F2 none XK_F2
-BX_KEY_F3 none XK_F3
-BX_KEY_F4 none XK_F4
-BX_KEY_F5 none XK_F5
-BX_KEY_F6 none XK_F6
-BX_KEY_F7 none XK_F7
-BX_KEY_F8 none XK_F8
-BX_KEY_F9 none XK_F9
-BX_KEY_F10 none XK_F10
-BX_KEY_F11 none XK_F11
-BX_KEY_F12 none XK_F12
-BX_KEY_ALT_L none XK_Alt_L
-BX_KEY_ALT_L none XK_Meta_L
-BX_KEY_ALT_R none XK_Alt_R
-BX_KEY_ALT_R none XK_Mode_switch
-BX_KEY_ALT_R none XK_Multi_key
-BX_KEY_BACKSLASH 'ù' XK_ugrave
-BX_KEY_BACKSLASH+BX_KEY_SHIFT_L '§' XK_section
-BX_KEY_LEFT_BACKSLASH+BX_KEY_SHIFT_L '>' XK_greater
-BX_KEY_LEFT_BACKSLASH '<' XK_less
-BX_KEY_BACKSPACE none XK_BackSpace
-BX_KEY_CAPS_LOCK none XK_Caps_Lock
-BX_KEY_COMMA ',' XK_comma
-BX_KEY_COMMA+BX_KEY_SHIFT_L ';' XK_semicolon
-BX_KEY_CTRL_L none XK_Control_L
-BX_KEY_CTRL_R none XK_Control_R
-BX_KEY_DELETE none XK_Delete
-BX_KEY_DOWN none XK_Down
-BX_KEY_END none XK_End
-BX_KEY_ENTER return XK_Return
-BX_KEY_EQUALS 'ì' XK_igrave
-BX_KEY_EQUALS+BX_KEY_SHIFT_L '^' XK_asciicircum
-BX_KEY_ESC none XK_Escape
-BX_KEY_GRAVE+BX_KEY_SHIFT_L '|' XK_bar
-BX_KEY_GRAVE backslash XK_backslash
-BX_KEY_HOME none XK_Home
-BX_KEY_INSERT none XK_Insert
-BX_KEY_KP_5 none XK_KP_5
-BX_KEY_KP_5 none XK_KP_Begin
-BX_KEY_KP_ADD none XK_KP_Add
-BX_KEY_KP_DELETE none XK_KP_Decimal
-BX_KEY_KP_DELETE none XK_KP_Delete
-BX_KEY_KP_DIVIDE none XK_KP_Divide
-BX_KEY_KP_DOWN none XK_KP_2
-BX_KEY_KP_DOWN none XK_KP_Down
-BX_KEY_KP_END none XK_KP_1
-BX_KEY_KP_END none XK_KP_End
-BX_KEY_KP_ENTER none XK_KP_Enter
-BX_KEY_KP_HOME none XK_KP_7
-BX_KEY_KP_HOME none XK_KP_Home
-BX_KEY_KP_INSERT none XK_KP_0
-BX_KEY_KP_INSERT none XK_KP_Insert
-BX_KEY_KP_LEFT none XK_KP_4
-BX_KEY_KP_LEFT none XK_KP_Left
-BX_KEY_KP_MULTIPLY none XK_KP_Multiply
-BX_KEY_KP_PAGE_DOWN none XK_KP_3
-BX_KEY_KP_PAGE_DOWN none XK_KP_Page_Down
-BX_KEY_KP_PAGE_UP none XK_KP_9
-BX_KEY_KP_PAGE_UP none XK_KP_Page_Up
-BX_KEY_KP_RIGHT none XK_KP_6
-BX_KEY_KP_RIGHT none XK_KP_Right
-BX_KEY_KP_SUBTRACT none XK_KP_Subtract
-BX_KEY_KP_UP none XK_KP_8
-BX_KEY_KP_UP none XK_KP_Up
-BX_KEY_LEFT none XK_Left
-BX_KEY_LEFT_BRACKET+BX_KEY_SHIFT_L 'é' XK_eacute
-BX_KEY_LEFT_BRACKET 'è' XK_egrave
-BX_KEY_MENU none XK_Menu
-BX_KEY_MINUS apostrophe XK_apostrophe
-BX_KEY_MINUS+BX_KEY_SHIFT_L '?' XK_question
-BX_KEY_NUM_LOCK none XK_Num_Lock
-BX_KEY_PAGE_DOWN none XK_Page_Down
-BX_KEY_PAGE_UP none XK_Page_Up
-BX_KEY_PAUSE none XK_Break
-BX_KEY_PAUSE none XK_Pause
-BX_KEY_PERIOD+BX_KEY_SHIFT_L ':' XK_colon
-BX_KEY_PERIOD '.' XK_period
-BX_KEY_PRINT none XK_Print
-BX_KEY_PRINT none XK_Sys_Req
-BX_KEY_RIGHT none XK_Right
-BX_KEY_RIGHT_BRACKET+BX_KEY_SHIFT_L '*' XK_asterisk
-BX_KEY_RIGHT_BRACKET '+' XK_plus
-BX_KEY_SCRL_LOCK none XK_Scroll_Lock
-BX_KEY_SEMICOLON+BX_KEY_SHIFT_L 'ç' XK_ccedilla
-BX_KEY_SEMICOLON 'ò' XK_ograve
-BX_KEY_SHIFT_L none XK_Shift_L
-BX_KEY_SHIFT_R none XK_Shift_R
-BX_KEY_SINGLE_QUOTE 'à' XK_agrave
-BX_KEY_SINGLE_QUOTE+BX_KEY_SHIFT_L '°' XK_degree
-BX_KEY_SLASH+BX_KEY_SHIFT_L '_' XK_underscore
-BX_KEY_SLASH '-' XK_minus
-BX_KEY_SPACE space XK_space
-BX_KEY_TAB none XK_ISO_Left_Tab
-BX_KEY_TAB tab XK_Tab
-BX_KEY_UP none XK_Up
-BX_KEY_WIN_L none XK_Super_L
-BX_KEY_WIN_R none XK_Super_R
+++ /dev/null
-# Bochs Keymap file
-# $Id: x11-pc-se.map,v 1.2 2002/09/25 08:00:25 bdenney Exp $
-# Target: PC(x86) keyboard, SE keymap
-# Author: Magnus 'Moggen' Öberg
-#
-# The keymap file describes the layout of a keyboard, and how it translates
-# into Bochs key codes.
-#
-# Format:
-# BX_Keysym ASCII_equivalent Xwin_Keysym
-#
-# Or, for keys that require modifiers:
-# BX_Keysym+BX_Modifier ASCII_equivalent Xwin_Keysym
-#
-# BX_Keysym and BX_Modifier must be present in the bx_key_symbol[] list in
-# gui/keymap.cc. The BX_Modifier is usually a shift key press, but it
-# could be any key. Presently a maximum of one modifier is supported, but this
-# could be changed in keymap.h (structure def has only one slot for modifier),
-# keymap.cc (parsing code), and iodev/keyboard.cc (simulate keypresses for >1
-# modifier).
-#
-# The ASCII_equivalent must be either apostrophe + one character + apostrophe,
-# or one of these keywords: space, return, tab, backslash, apostrophe, none.
-# This format is designed to look like a char constant in C, but it's a very
-# simple parser. There's no concept of backslash being an escape char. The
-# backslash and apostrophe entries are provided for aesthetic purposes only: no
-# C++ programmer wants to see '\' or '''. The parser doesn't care, but they are
-# ugly.
-#
-# Xwin_Keysym is the X windows equivalent of the key combination. These
-# codes should match whatever you find in /usr/X11R6/include/X11/keysymdef.h.
-# If you're running X windows, Bochs will take each of these Xwin_Keysyms,
-# pull off the XK_ in front, and use XStringToKeysym() to change them into
-# numerical codes. If this lookup fails, you will get a panic and you need
-# to edit the keymap file.
-#
-
-# Upper key groups
-BX_KEY_ESC none XK_Escape
-
-BX_KEY_F1 none XK_F1
-BX_KEY_F2 none XK_F2
-BX_KEY_F3 none XK_F3
-BX_KEY_F4 none XK_F4
-
-BX_KEY_F5 none XK_F5
-BX_KEY_F6 none XK_F6
-BX_KEY_F7 none XK_F7
-BX_KEY_F8 none XK_F8
-
-BX_KEY_F9 none XK_F9
-BX_KEY_F10 none XK_F10
-BX_KEY_F11 none XK_F11
-BX_KEY_F12 none XK_F12
-
-BX_KEY_PRINT none XK_Print
-BX_KEY_PRINT none XK_Sys_Req
-BX_KEY_SCRL_LOCK none XK_Scroll_Lock
-BX_KEY_PAUSE none XK_Break
-BX_KEY_PAUSE none XK_Pause
-
-# Main key group
-# Row 1
-BX_KEY_GRAVE '§' XK_section
-BX_KEY_GRAVE+BX_KEY_SHIFT_L '½' XK_onehalf
-BX_KEY_GRAVE+BX_KEY_ALT_R '¶' XK_paragraph
-BX_KEY_GRAVE+BX_KEY_SHIFT_L+BX_KEY_ALT_R '¾' XK_threequarters
-BX_KEY_1 '1' XK_1
-BX_KEY_1+BX_KEY_SHIFT_L '!' XK_exclam
-BX_KEY_1+BX_KEY_ALT_R '¡' XK_exclamdown
-BX_KEY_1+BX_KEY_SHIFT_L+BX_KEY_ALT_R '¹' XK_onesuperior
-BX_KEY_2 '2' XK_2
-BX_KEY_2+BX_KEY_SHIFT_L '"' XK_quotedbl
-BX_KEY_2+BX_KEY_ALT_R '@' XK_at
-BX_KEY_2+BX_KEY_SHIFT_L+BX_KEY_ALT_R '²' XK_twosuperior
-BX_KEY_3 '3' XK_3
-BX_KEY_3+BX_KEY_SHIFT_L '#' XK_numbersign
-BX_KEY_3+BX_KEY_ALT_R '£' XK_sterling
-BX_KEY_3+BX_KEY_SHIFT_L+BX_KEY_ALT_R '³' XK_threesuperior
-BX_KEY_4 '4' XK_4
-BX_KEY_4+BX_KEY_SHIFT_L '¤' XK_currency
-BX_KEY_4+BX_KEY_ALT_R '$' XK_dollar
-BX_KEY_4+BX_KEY_SHIFT_L+BX_KEY_ALT_R '¼' XK_onequarter
-BX_KEY_5 '5' XK_5
-BX_KEY_5+BX_KEY_SHIFT_L '%' XK_percent
-BX_KEY_5+BX_KEY_SHIFT_L+BX_KEY_ALT_R '¢' XK_cent
-BX_KEY_6 '6' XK_6
-BX_KEY_6+BX_KEY_SHIFT_L '&' XK_ampersand
-BX_KEY_6+BX_KEY_ALT_R '¥' XK_yen
-BX_KEY_7 '7' XK_7
-BX_KEY_7+BX_KEY_SHIFT_L '/' XK_slash
-BX_KEY_7+BX_KEY_ALT_R '{' XK_braceleft
-BX_KEY_7+BX_KEY_SHIFT_L+BX_KEY_ALT_R '÷' XK_division
-BX_KEY_8 '8' XK_8
-BX_KEY_8+BX_KEY_SHIFT_L '(' XK_parenleft
-BX_KEY_8+BX_KEY_ALT_R '[' XK_bracketleft
-BX_KEY_9 '9' XK_9
-BX_KEY_9+BX_KEY_SHIFT_L ')' XK_parenright
-BX_KEY_9+BX_KEY_ALT_R ']' XK_bracketright
-BX_KEY_0 '0' XK_0
-BX_KEY_0+BX_KEY_SHIFT_L '=' XK_equal
-BX_KEY_0+BX_KEY_ALT_R '}' XK_braceright
-BX_KEY_0+BX_KEY_SHIFT_L+BX_KEY_ALT_R '°' XK_degree
-BX_KEY_MINUS '+' XK_plus
-BX_KEY_MINUS+BX_KEY_SHIFT_L '?' XK_question
-BX_KEY_MINUS+BX_KEY_ALT_L backslash XK_backslash
-BX_KEY_MINUS+BX_KEY_SHIFT_L+BX_KEY_ALT_R '¿' XK_questiondown
-BX_KEY_EQUALS none XK_dead_acute
-BX_KEY_EQUALS+BX_KEY_SHIFT_L none XK_dead_grave
-BX_KEY_EQUALS+BX_KEY_ALT_L '±' XK_plusminus
-BX_KEY_EQUALS+BX_KEY_ALT_L+BX_KEY_ALT_R '¬' XK_notsign
-BX_KEY_BACKSPACE none XK_BackSpace
-
-# Row 2
-BX_KEY_TAB tab XK_Tab
-BX_KEY_TAB none XK_ISO_Left_Tab
-BX_KEY_Q 'q' XK_q
-BX_KEY_Q+BX_KEY_SHIFT_L 'Q' XK_Q
-BX_KEY_W 'w' XK_w
-BX_KEY_W+BX_KEY_SHIFT_L 'W' XK_W
-BX_KEY_E 'e' XK_e
-BX_KEY_E+BX_KEY_SHIFT_L 'E' XK_E
-BX_KEY_E+BX_KEY_SHIFT_L+BX_KEY_ALT_R none XK_EuroSign
-BX_KEY_R 'r' XK_r
-BX_KEY_R+BX_KEY_SHIFT_L 'R' XK_R
-BX_KEY_R+BX_KEY_ALT_R '®' XK_registered
-BX_KEY_T 't' XK_t
-BX_KEY_T+BX_KEY_SHIFT_L 'T' XK_T
-BX_KEY_T+BX_KEY_ALT_R 'þ' XK_thorn
-BX_KEY_T+BX_KEY_SHIFT_L+BX_KEY_ALT_R 'Þ' XK_THORN
-BX_KEY_Y 'y' XK_y
-BX_KEY_Y+BX_KEY_SHIFT_L 'Y' XK_Y
-BX_KEY_U 'u' XK_u
-BX_KEY_U+BX_KEY_SHIFT_L 'U' XK_U
-BX_KEY_I 'i' XK_i
-BX_KEY_I+BX_KEY_SHIFT_L 'I' XK_I
-BX_KEY_O 'o' XK_o
-BX_KEY_O+BX_KEY_SHIFT_L 'O' XK_O
-BX_KEY_P 'p' XK_p
-BX_KEY_P+BX_KEY_SHIFT_L 'P' XK_P
-BX_KEY_LEFT_BRACKET 'å' XK_aring
-BX_KEY_LEFT_BRACKET+BX_KEY_SHIFT_L 'Å' XK_Aring
-BX_KEY_RIGHT_BRACKET none XK_dead_diaeresis
-BX_KEY_RIGHT_BRACKET+BX_KEY_SHIFT_L none XK_dead_circumflex
-BX_KEY_RIGHT_BRACKET+BX_KEY_ALT_R none XK_dead_tilde
-BX_KEY_ENTER return XK_Return
-
-# Row 3
-BX_KEY_CAPS_LOCK none XK_Caps_Lock
-BX_KEY_A 'a' XK_a
-BX_KEY_A+BX_KEY_SHIFT_L 'A' XK_A
-BX_KEY_A+BX_KEY_ALT_R 'ª' XK_ordfeminine
-BX_KEY_A+BX_KEY_SHIFT_L+BX_KEY_ALT_R 'º' XK_masculine
-BX_KEY_S 's' XK_s
-BX_KEY_S+BX_KEY_SHIFT_L 'S' XK_S
-BX_KEY_S+BX_KEY_ALT_R 'ß' XK_ssharp
-BX_KEY_D 'd' XK_d
-BX_KEY_D+BX_KEY_SHIFT_L 'D' XK_D
-BX_KEY_D+BX_KEY_ALT_R 'ð' XK_eth
-BX_KEY_D+BX_KEY_SHIFT_L+BX_KEY_ALT_R 'Ð' XK_ETH
-BX_KEY_F 'f' XK_f
-BX_KEY_F+BX_KEY_SHIFT_L 'F' XK_F
-BX_KEY_G 'g' XK_g
-BX_KEY_G+BX_KEY_SHIFT_L 'G' XK_G
-BX_KEY_H 'h' XK_h
-BX_KEY_H+BX_KEY_SHIFT_L 'H' XK_H
-BX_KEY_J 'j' XK_j
-BX_KEY_J+BX_KEY_SHIFT_L 'J' XK_J
-BX_KEY_K 'k' XK_k
-BX_KEY_K+BX_KEY_SHIFT_L 'K' XK_K
-BX_KEY_L 'l' XK_l
-BX_KEY_L+BX_KEY_SHIFT_L 'L' XK_L
-BX_KEY_SEMICOLON 'ö' XK_odiaeresis
-BX_KEY_SEMICOLON+BX_KEY_SHIFT_L 'Ö' XK_Odiaeresis
-BX_KEY_SEMICOLON+BX_KEY_ALT_R 'ø' XK_oslash
-BX_KEY_SEMICOLON+BX_KEY_SHIFT_L+BX_KEY_ALT_R 'Ø' XK_Ooblique
-BX_KEY_SINGLE_QUOTE 'ä' XK_adiaeresis
-BX_KEY_SINGLE_QUOTE+BX_KEY_SHIFT_L 'Ä' XK_Adiaeresis
-BX_KEY_SINGLE_QUOTE+BX_KEY_ALT_R 'æ' XK_ae
-BX_KEY_SINGLE_QUOTE+BX_KEY_SHIFT_L+BX_KEY_ALT_R 'Æ' XK_AE
-BX_KEY_BACKSLASH apostrophe XK_apostrophe
-BX_KEY_BACKSLASH+BX_KEY_SHIFT_L '*' XK_asterisk
-BX_KEY_BACKSLASH+BX_KEY_ALT_R '´' XK_acute
-BX_KEY_BACKSLASH+BX_KEY_SHIFT_L+BX_KEY_ALT_R '×' XK_multiply
-
-# Row 4
-BX_KEY_SHIFT_L none XK_Shift_L
-BX_KEY_LEFT_BACKSLASH '<' XK_less
-BX_KEY_LEFT_BACKSLASH+BX_KEY_SHIFT_L '>' XK_greater
-BX_KEY_LEFT_BACKSLASH+BX_KEY_ALT_R '|' XK_bar
-BX_KEY_LEFT_BACKSLASH+BX_KEY_SHIFT_L+BX_KEY_ALT_R '¦' XK_brokenbar
-BX_KEY_Z 'z' XK_z
-BX_KEY_Z+BX_KEY_SHIFT_L 'Z' XK_Z
-BX_KEY_Z+BX_KEY_ALT_R '«' XK_guillemotleft
-BX_KEY_X 'x' XK_x
-BX_KEY_X+BX_KEY_SHIFT_L 'X' XK_X
-BX_KEY_X+BX_KEY_ALT_R '»' XK_guillemotright
-BX_KEY_C 'c' XK_c
-BX_KEY_C+BX_KEY_SHIFT_L 'C' XK_C
-BX_KEY_C+BX_KEY_ALT_R '©' XK_copyright
-BX_KEY_V 'v' XK_v
-BX_KEY_V+BX_KEY_SHIFT_L 'V' XK_V
-BX_KEY_V+BX_KEY_SHIFT_L+BX_KEY_ALT_R '`' XK_grave
-BX_KEY_B 'b' XK_b
-BX_KEY_B+BX_KEY_SHIFT_L 'B' XK_B
-BX_KEY_N 'n' XK_n
-BX_KEY_N+BX_KEY_SHIFT_L 'N' XK_N
-BX_KEY_M 'm' XK_m
-BX_KEY_M+BX_KEY_SHIFT_L 'M' XK_M
-BX_KEY_M+BX_KEY_ALT_R 'µ' XK_mu
-BX_KEY_COMMA ',' XK_comma
-BX_KEY_COMMA+BX_KEY_SHIFT_L ';' XK_semicolon
-BX_KEY_PERIOD '.' XK_period
-BX_KEY_PERIOD+BX_KEY_SHIFT_L ':' XK_colon
-BX_KEY_PERIOD+BX_KEY_ALT_R '·' XK_periodcentered
-BX_KEY_SLASH '-' XK_minus
-BX_KEY_SLASH+BX_KEY_SHIFT '_' XK_underscore
-BX_KEY_SLASH+BX_KEY_ALT_R '' XK_hyphen
-BX_KEY_SLASH+BX_KEY_SHIFT+BX_KEY_ALT_R '' XK_macron
-BX_KEY_SHIFT_R none XK_Shift_R
-
-# Row 5
-BX_KEY_CTRL_L none XK_Control_L
-BX_KEY_WIN_L none XK_Super_L
-BX_KEY_ALT_L none XK_Alt_L
-BX_KEY_ALT_L none XK_Meta_L
-BX_KEY_SPACE space XK_space
-BX_KEY_SPACE+BX_KEY_ALT_R none XK_nobreakspace
-BX_KEY_ALT_R none XK_Alt_R
-BX_KEY_ALT_R none XK_Mode_switch
-BX_KEY_ALT_R none XK_Multi_key
-BX_KEY_WIN_R none XK_Super_R
-BX_KEY_MENU none XK_Menu
-BX_KEY_CTRL_R none XK_Control_R
-
-# Ins/Del/Home/End/PgUp/PgDn
-BX_KEY_INSERT none XK_Insert
-BX_KEY_DELETE none XK_Delete
-BX_KEY_HOME none XK_Home
-BX_KEY_END none XK_End
-BX_KEY_PAGE_UP none XK_Page_Up
-BX_KEY_PAGE_DOWN none XK_Page_Down
-
-# Arrow keys
-BX_KEY_LEFT none XK_Left
-BX_KEY_RIGHT none XK_Right
-BX_KEY_UP none XK_Up
-BX_KEY_DOWN none XK_Down
-
-# Numerical keypad
-BX_KEY_NUM_LOCK none XK_Num_Lock
-BX_KEY_KP_DIVIDE none XK_KP_Divide
-BX_KEY_KP_MULTIPLY none XK_KP_Multiply
-BX_KEY_KP_SUBTRACT none XK_KP_Subtract
-BX_KEY_KP_ADD none XK_KP_Add
-BX_KEY_KP_ENTER none XK_KP_Enter
-BX_KEY_KP_HOME none XK_KP_7
-BX_KEY_KP_HOME none XK_KP_Home
-BX_KEY_KP_UP none XK_KP_8
-BX_KEY_KP_UP none XK_KP_Up
-BX_KEY_KP_PAGE_UP none XK_KP_9
-BX_KEY_KP_PAGE_UP none XK_KP_Page_Up
-BX_KEY_KP_LEFT none XK_KP_4
-BX_KEY_KP_LEFT none XK_KP_Left
-BX_KEY_KP_5 none XK_KP_5
-BX_KEY_KP_5 none XK_KP_Begin
-BX_KEY_KP_RIGHT none XK_KP_6
-BX_KEY_KP_RIGHT none XK_KP_Right
-BX_KEY_KP_END none XK_KP_1
-BX_KEY_KP_END none XK_KP_End
-BX_KEY_KP_DOWN none XK_KP_2
-BX_KEY_KP_DOWN none XK_KP_Down
-BX_KEY_KP_PAGE_DOWN none XK_KP_3
-BX_KEY_KP_PAGE_DOWN none XK_KP_Page_Down
-BX_KEY_KP_INSERT none XK_KP_0
-BX_KEY_KP_INSERT none XK_KP_Insert
-BX_KEY_KP_DELETE none XK_KP_Decimal
-BX_KEY_KP_DELETE none XK_KP_Delete
+++ /dev/null
-# Bochs Keymap file
-# $Id: x11-pc-uk.map,v 1.1 2002/12/11 21:35:50 bdenney Exp $
-# Target: PC(x86) keyboard, UK keymap
-# Author: Denis Lenihan
-#
-# The keymap file describes the layout of a keyboard, and how it translates
-# into Bochs key codes.
-#
-# Format:
-# BX_Keysym ASCII_equivalent Xwin_Keysym
-#
-# Or, for keys that require modifiers:
-# BX_Keysym+BX_Modifier ASCII_equivalent Xwin_Keysym
-#
-# BX_Keysym and BX_Modifier must be present in the bx_key_symbol[] list in
-# gui/keymap.cc. The BX_Modifier is usually a shift key press, but it
-# could be any key. Presently a maximum of one modifier is supported, but this
-# could be changed in keymap.h (structure def has only one slot for modifier),
-# keymap.cc (parsing code), and iodev/keyboard.cc (simulate keypresses for >1
-# modifier).
-#
-# The ASCII_equivalent must be either apostrophe + one character + apostrophe,
-# or one of these keywords: space, return, tab, backslash, apostrophe, none.
-# This format is designed to look like a char constant in C, but it's a very
-# simple parser. There's no concept of backslash being an escape char. The
-# backslash and apostrophe entries are provided for aesthetic purposes only: no
-# C++ programmer wants to see '\' or '''. The parser doesn't care, but they are
-# ugly.
-#
-# Xwin_Keysym is the X windows equivalent of the key combination. These
-# codes should match whatever you find in /usr/X11R6/include/X11/keysymdef.h.
-# If you're running X windows, Bochs will take each of these Xwin_Keysyms,
-# pull off the XK_ in front, and use XStringToKeysym() to change them into
-# numerical codes. If this lookup fails, you will get a panic and you need
-# to edit the keymap file.
-#
-
-BX_KEY_0 '0' XK_0
-BX_KEY_0+BX_KEY_SHIFT_L ')' XK_parenright
-BX_KEY_1 '1' XK_1
-BX_KEY_1+BX_KEY_SHIFT_L '!' XK_exclam
-BX_KEY_2 '2' XK_2
-BX_KEY_2+BX_KEY_SHIFT_L '"' XK_quotedbl
-BX_KEY_3 '3' XK_3
-BX_KEY_3+BX_KEY_SHIFT_L '£' XK_sterling
-BX_KEY_3+BX_KEY_ALT_R '|' XK_EuroSign
-BX_KEY_4 '4' XK_4
-BX_KEY_4+BX_KEY_SHIFT_L '$' XK_dollar
-BX_KEY_5 '5' XK_5
-BX_KEY_5+BX_KEY_SHIFT_L '%' XK_percent
-BX_KEY_6 '6' XK_6
-BX_KEY_6+BX_KEY_SHIFT_L '^' XK_asciicircum
-BX_KEY_7 '7' XK_7
-BX_KEY_7+BX_KEY_SHIFT_L '&' XK_ampersand
-BX_KEY_8 '8' XK_8
-BX_KEY_8+BX_KEY_SHIFT_L '*' XK_asterisk
-BX_KEY_9 '9' XK_9
-BX_KEY_9+BX_KEY_SHIFT_L '(' XK_parenleft
-BX_KEY_A+BX_KEY_SHIFT_L 'A' XK_A
-BX_KEY_A 'a' XK_a
-BX_KEY_B+BX_KEY_SHIFT_L 'B' XK_B
-BX_KEY_B 'b' XK_b
-BX_KEY_C+BX_KEY_SHIFT_L 'C' XK_C
-BX_KEY_C 'c' XK_c
-BX_KEY_D+BX_KEY_SHIFT_L 'D' XK_D
-BX_KEY_D 'd' XK_d
-BX_KEY_E+BX_KEY_SHIFT_L 'E' XK_E
-BX_KEY_E 'e' XK_e
-BX_KEY_F+BX_KEY_SHIFT_L 'F' XK_F
-BX_KEY_F 'f' XK_f
-BX_KEY_G+BX_KEY_SHIFT_L 'G' XK_G
-BX_KEY_G 'g' XK_g
-BX_KEY_H+BX_KEY_SHIFT_L 'H' XK_H
-BX_KEY_H 'h' XK_h
-BX_KEY_I+BX_KEY_SHIFT_L 'I' XK_I
-BX_KEY_I 'i' XK_i
-BX_KEY_J+BX_KEY_SHIFT_L 'J' XK_J
-BX_KEY_J 'j' XK_j
-BX_KEY_K+BX_KEY_SHIFT_L 'K' XK_K
-BX_KEY_K 'k' XK_k
-BX_KEY_L+BX_KEY_SHIFT_L 'L' XK_L
-BX_KEY_L 'l' XK_l
-BX_KEY_M+BX_KEY_SHIFT_L 'M' XK_M
-BX_KEY_M 'm' XK_m
-BX_KEY_N+BX_KEY_SHIFT_L 'N' XK_N
-BX_KEY_N 'n' XK_n
-BX_KEY_O+BX_KEY_SHIFT_L 'O' XK_O
-BX_KEY_O 'o' XK_o
-BX_KEY_P+BX_KEY_SHIFT_L 'P' XK_P
-BX_KEY_P 'p' XK_p
-BX_KEY_Q+BX_KEY_SHIFT_L 'Q' XK_Q
-BX_KEY_Q 'q' XK_q
-BX_KEY_R+BX_KEY_SHIFT_L 'R' XK_R
-BX_KEY_R 'r' XK_r
-BX_KEY_S+BX_KEY_SHIFT_L 'S' XK_S
-BX_KEY_S 's' XK_s
-BX_KEY_T+BX_KEY_SHIFT_L 'T' XK_T
-BX_KEY_T 't' XK_t
-BX_KEY_U+BX_KEY_SHIFT_L 'U' XK_U
-BX_KEY_U 'u' XK_u
-BX_KEY_V+BX_KEY_SHIFT_L 'V' XK_V
-BX_KEY_V 'v' XK_v
-BX_KEY_W+BX_KEY_SHIFT_L 'W' XK_W
-BX_KEY_W 'w' XK_w
-BX_KEY_X+BX_KEY_SHIFT_L 'X' XK_X
-BX_KEY_X 'x' XK_x
-BX_KEY_Y+BX_KEY_SHIFT_L 'Y' XK_Y
-BX_KEY_Y 'y' XK_y
-BX_KEY_Z+BX_KEY_SHIFT_L 'Z' XK_Z
-BX_KEY_Z 'z' XK_z
-BX_KEY_F1 none XK_F1
-BX_KEY_F2 none XK_F2
-BX_KEY_F3 none XK_F3
-BX_KEY_F4 none XK_F4
-BX_KEY_F5 none XK_F5
-BX_KEY_F6 none XK_F6
-BX_KEY_F7 none XK_F7
-BX_KEY_F8 none XK_F8
-BX_KEY_F9 none XK_F9
-BX_KEY_F10 none XK_F10
-BX_KEY_F11 none XK_F11
-BX_KEY_F12 none XK_F12
-BX_KEY_ALT_L none XK_Alt_L
-BX_KEY_ALT_L none XK_Meta_L
-BX_KEY_ALT_R none XK_Alt_R
-BX_KEY_ALT_R none XK_Mode_switch
-BX_KEY_ALT_R none XK_Multi_key
-BX_KEY_LEFT_BACKSLASH '\' XK_backslash
-BX_KEY_LEFT_BACKSLASH+BX_KEY_SHIFT_L '|' XK_bar
-BX_KEY_BACKSLASH '~' XK_asciitilde
-BX_KEY_BACKSLASH+BX_KEY_SHIFT_L '#' XK_numbersign
-BX_KEY_BACKSPACE none XK_BackSpace
-BX_KEY_CAPS_LOCK none XK_Caps_Lock
-BX_KEY_COMMA ',' XK_comma
-BX_KEY_COMMA+BX_KEY_SHIFT_L '<' XK_less
-BX_KEY_CTRL_L none XK_Control_L
-BX_KEY_CTRL_R none XK_Control_R
-BX_KEY_DELETE none XK_Delete
-BX_KEY_DOWN none XK_Down
-BX_KEY_END none XK_End
-BX_KEY_ENTER return XK_Return
-BX_KEY_EQUALS '=' XK_equal
-BX_KEY_EQUALS+BX_KEY_SHIFT_L '+' XK_plus
-BX_KEY_ESC none XK_Escape
-BX_KEY_GRAVE+BX_KEY_SHIFT_L '¬' XK_notsign
-BX_KEY_GRAVE '`' XK_grave
-BX_KEY_GRAVE+BX_KEY_ALT_R '|' XK_bar
-BX_KEY_HOME none XK_Home
-BX_KEY_INSERT none XK_Insert
-BX_KEY_KP_5 none XK_KP_5
-BX_KEY_KP_5 none XK_KP_Begin
-BX_KEY_KP_ADD none XK_KP_Add
-BX_KEY_KP_DELETE none XK_KP_Decimal
-BX_KEY_KP_DELETE none XK_KP_Delete
-BX_KEY_KP_DIVIDE none XK_KP_Divide
-BX_KEY_KP_DOWN none XK_KP_2
-BX_KEY_KP_DOWN none XK_KP_Down
-BX_KEY_KP_END none XK_KP_1
-BX_KEY_KP_END none XK_KP_End
-BX_KEY_KP_ENTER none XK_KP_Enter
-BX_KEY_KP_HOME none XK_KP_7
-BX_KEY_KP_HOME none XK_KP_Home
-BX_KEY_KP_INSERT none XK_KP_0
-BX_KEY_KP_INSERT none XK_KP_Insert
-BX_KEY_KP_LEFT none XK_KP_4
-BX_KEY_KP_LEFT none XK_KP_Left
-BX_KEY_KP_MULTIPLY none XK_KP_Multiply
-BX_KEY_KP_PAGE_DOWN none XK_KP_3
-BX_KEY_KP_PAGE_DOWN none XK_KP_Page_Down
-BX_KEY_KP_PAGE_UP none XK_KP_9
-BX_KEY_KP_PAGE_UP none XK_KP_Page_Up
-BX_KEY_KP_RIGHT none XK_KP_6
-BX_KEY_KP_RIGHT none XK_KP_Right
-BX_KEY_KP_SUBTRACT none XK_KP_Subtract
-BX_KEY_KP_UP none XK_KP_8
-BX_KEY_KP_UP none XK_KP_Up
-BX_KEY_LEFT none XK_Left
-BX_KEY_LEFT_BRACKET+BX_KEY_SHIFT_L '{' XK_braceleft
-BX_KEY_LEFT_BRACKET '[' XK_bracketleft
-BX_KEY_MENU none XK_Menu
-BX_KEY_MINUS '-' XK_minus
-BX_KEY_MINUS+BX_KEY_SHIFT_L '_' XK_underscore
-BX_KEY_NUM_LOCK none XK_Num_Lock
-BX_KEY_PAGE_DOWN none XK_Page_Down
-BX_KEY_PAGE_UP none XK_Page_Up
-BX_KEY_PAUSE none XK_Break
-BX_KEY_PAUSE none XK_Pause
-BX_KEY_PERIOD+BX_KEY_SHIFT_L '>' XK_greater
-BX_KEY_PERIOD '.' XK_period
-BX_KEY_PRINT none XK_Print
-BX_KEY_PRINT none XK_Sys_Req
-BX_KEY_RIGHT none XK_Right
-BX_KEY_RIGHT_BRACKET+BX_KEY_SHIFT_L '}' XK_braceright
-BX_KEY_RIGHT_BRACKET ']' XK_bracketright
-BX_KEY_SCRL_LOCK none XK_Scroll_Lock
-BX_KEY_SEMICOLON+BX_KEY_SHIFT_L ':' XK_colon
-BX_KEY_SEMICOLON ';' XK_semicolon
-BX_KEY_SHIFT_L none XK_Shift_L
-BX_KEY_SHIFT_R none XK_Shift_R
-BX_KEY_SINGLE_QUOTE apostrophe XK_apostrophe
-BX_KEY_SINGLE_QUOTE+BX_KEY_SHIFT_L '@' XK_at
-BX_KEY_SLASH+BX_KEY_SHIFT_L '?' XK_question
-BX_KEY_SLASH '/' XK_slash
-BX_KEY_SPACE space XK_space
-BX_KEY_TAB none XK_ISO_Left_Tab
-BX_KEY_TAB tab XK_Tab
-BX_KEY_UP none XK_Up
-BX_KEY_WIN_L none XK_Super_L
-BX_KEY_WIN_R none XK_Super_R
+++ /dev/null
-# Bochs Keymap file
-# $Id: x11-pc-us.map,v 1.3 2002/09/25 08:00:25 bdenney Exp $
-# Target: PC(x86) keyboard, US keymap
-# Author: Christophe Bothamy, Bryce Denney
-#
-# The keymap file describes the layout of a keyboard, and how it translates
-# into Bochs key codes.
-#
-# Format:
-# BX_Keysym ASCII_equivalent Xwin_Keysym
-#
-# Or, for keys that require modifiers:
-# BX_Keysym+BX_Modifier ASCII_equivalent Xwin_Keysym
-#
-# BX_Keysym and BX_Modifier must be present in the bx_key_symbol[] list in
-# gui/keymap.cc. The BX_Modifier is usually a shift key press, but it
-# could be any key. Presently a maximum of one modifier is supported, but this
-# could be changed in keymap.h (structure def has only one slot for modifier),
-# keymap.cc (parsing code), and iodev/keyboard.cc (simulate keypresses for >1
-# modifier).
-#
-# The ASCII_equivalent must be either apostrophe + one character + apostrophe,
-# or one of these keywords: space, return, tab, backslash, apostrophe, none.
-# This format is designed to look like a char constant in C, but it's a very
-# simple parser. There's no concept of backslash being an escape char. The
-# backslash and apostrophe entries are provided for aesthetic purposes only: no
-# C++ programmer wants to see '\' or '''. The parser doesn't care, but they are
-# ugly.
-#
-# Xwin_Keysym is the X windows equivalent of the key combination. These
-# codes should match whatever you find in /usr/X11R6/include/X11/keysymdef.h.
-# If you're running X windows, Bochs will take each of these Xwin_Keysyms,
-# pull off the XK_ in front, and use XStringToKeysym() to change them into
-# numerical codes. If this lookup fails, you will get a panic and you need
-# to edit the keymap file.
-#
-
-BX_KEY_0 '0' XK_0
-BX_KEY_0+BX_KEY_SHIFT_L ')' XK_parenright
-BX_KEY_1 '1' XK_1
-BX_KEY_1+BX_KEY_SHIFT_L '!' XK_exclam
-BX_KEY_2 '2' XK_2
-BX_KEY_2+BX_KEY_SHIFT_L '@' XK_at
-BX_KEY_3 '3' XK_3
-BX_KEY_3+BX_KEY_SHIFT_L '#' XK_numbersign
-BX_KEY_4 '4' XK_4
-BX_KEY_4+BX_KEY_SHIFT_L '$' XK_dollar
-BX_KEY_5 '5' XK_5
-BX_KEY_5+BX_KEY_SHIFT_L '%' XK_percent
-BX_KEY_6 '6' XK_6
-BX_KEY_6+BX_KEY_SHIFT_L '^' XK_asciicircum
-BX_KEY_7 '7' XK_7
-BX_KEY_7+BX_KEY_SHIFT_L '&' XK_ampersand
-BX_KEY_8 '8' XK_8
-BX_KEY_8+BX_KEY_SHIFT_L '*' XK_asterisk
-BX_KEY_9 '9' XK_9
-BX_KEY_9+BX_KEY_SHIFT_L '(' XK_parenleft
-BX_KEY_A+BX_KEY_SHIFT_L 'A' XK_A
-BX_KEY_A 'a' XK_a
-BX_KEY_B+BX_KEY_SHIFT_L 'B' XK_B
-BX_KEY_B 'b' XK_b
-BX_KEY_C+BX_KEY_SHIFT_L 'C' XK_C
-BX_KEY_C 'c' XK_c
-BX_KEY_D+BX_KEY_SHIFT_L 'D' XK_D
-BX_KEY_D 'd' XK_d
-BX_KEY_E+BX_KEY_SHIFT_L 'E' XK_E
-BX_KEY_E 'e' XK_e
-BX_KEY_F+BX_KEY_SHIFT_L 'F' XK_F
-BX_KEY_F 'f' XK_f
-BX_KEY_G+BX_KEY_SHIFT_L 'G' XK_G
-BX_KEY_G 'g' XK_g
-BX_KEY_H+BX_KEY_SHIFT_L 'H' XK_H
-BX_KEY_H 'h' XK_h
-BX_KEY_I+BX_KEY_SHIFT_L 'I' XK_I
-BX_KEY_I 'i' XK_i
-BX_KEY_J+BX_KEY_SHIFT_L 'J' XK_J
-BX_KEY_J 'j' XK_j
-BX_KEY_K+BX_KEY_SHIFT_L 'K' XK_K
-BX_KEY_K 'k' XK_k
-BX_KEY_L+BX_KEY_SHIFT_L 'L' XK_L
-BX_KEY_L 'l' XK_l
-BX_KEY_M+BX_KEY_SHIFT_L 'M' XK_M
-BX_KEY_M 'm' XK_m
-BX_KEY_N+BX_KEY_SHIFT_L 'N' XK_N
-BX_KEY_N 'n' XK_n
-BX_KEY_O+BX_KEY_SHIFT_L 'O' XK_O
-BX_KEY_O 'o' XK_o
-BX_KEY_P+BX_KEY_SHIFT_L 'P' XK_P
-BX_KEY_P 'p' XK_p
-BX_KEY_Q+BX_KEY_SHIFT_L 'Q' XK_Q
-BX_KEY_Q 'q' XK_q
-BX_KEY_R+BX_KEY_SHIFT_L 'R' XK_R
-BX_KEY_R 'r' XK_r
-BX_KEY_S+BX_KEY_SHIFT_L 'S' XK_S
-BX_KEY_S 's' XK_s
-BX_KEY_T+BX_KEY_SHIFT_L 'T' XK_T
-BX_KEY_T 't' XK_t
-BX_KEY_U+BX_KEY_SHIFT_L 'U' XK_U
-BX_KEY_U 'u' XK_u
-BX_KEY_V+BX_KEY_SHIFT_L 'V' XK_V
-BX_KEY_V 'v' XK_v
-BX_KEY_W+BX_KEY_SHIFT_L 'W' XK_W
-BX_KEY_W 'w' XK_w
-BX_KEY_X+BX_KEY_SHIFT_L 'X' XK_X
-BX_KEY_X 'x' XK_x
-BX_KEY_Y+BX_KEY_SHIFT_L 'Y' XK_Y
-BX_KEY_Y 'y' XK_y
-BX_KEY_Z+BX_KEY_SHIFT_L 'Z' XK_Z
-BX_KEY_Z 'z' XK_z
-BX_KEY_F1 none XK_F1
-BX_KEY_F2 none XK_F2
-BX_KEY_F3 none XK_F3
-BX_KEY_F4 none XK_F4
-BX_KEY_F5 none XK_F5
-BX_KEY_F6 none XK_F6
-BX_KEY_F7 none XK_F7
-BX_KEY_F8 none XK_F8
-BX_KEY_F9 none XK_F9
-BX_KEY_F10 none XK_F10
-BX_KEY_F11 none XK_F11
-BX_KEY_F12 none XK_F12
-BX_KEY_ALT_L none XK_Alt_L
-BX_KEY_ALT_L none XK_Meta_L
-BX_KEY_ALT_R none XK_Alt_R
-BX_KEY_ALT_R none XK_Mode_switch
-BX_KEY_ALT_R none XK_Multi_key
-BX_KEY_BACKSLASH backslash XK_backslash
-BX_KEY_BACKSLASH+BX_KEY_SHIFT_L '|' XK_bar
-BX_KEY_BACKSPACE none XK_BackSpace
-BX_KEY_CAPS_LOCK none XK_Caps_Lock
-BX_KEY_COMMA ',' XK_comma
-BX_KEY_COMMA+BX_KEY_SHIFT_L '<' XK_less
-BX_KEY_CTRL_L none XK_Control_L
-BX_KEY_CTRL_R none XK_Control_R
-BX_KEY_DELETE none XK_Delete
-BX_KEY_DOWN none XK_Down
-BX_KEY_END none XK_End
-BX_KEY_ENTER return XK_Return
-BX_KEY_EQUALS '=' XK_equal
-BX_KEY_EQUALS+BX_KEY_SHIFT_L '+' XK_plus
-BX_KEY_ESC none XK_Escape
-BX_KEY_GRAVE+BX_KEY_SHIFT_L '~' XK_asciitilde
-BX_KEY_GRAVE '`' XK_grave
-BX_KEY_HOME none XK_Home
-BX_KEY_INSERT none XK_Insert
-BX_KEY_KP_5 none XK_KP_5
-BX_KEY_KP_5 none XK_KP_Begin
-BX_KEY_KP_ADD none XK_KP_Add
-BX_KEY_KP_DELETE none XK_KP_Decimal
-BX_KEY_KP_DELETE none XK_KP_Delete
-BX_KEY_KP_DIVIDE none XK_KP_Divide
-BX_KEY_KP_DOWN none XK_KP_2
-BX_KEY_KP_DOWN none XK_KP_Down
-BX_KEY_KP_END none XK_KP_1
-BX_KEY_KP_END none XK_KP_End
-BX_KEY_KP_ENTER none XK_KP_Enter
-BX_KEY_KP_HOME none XK_KP_7
-BX_KEY_KP_HOME none XK_KP_Home
-BX_KEY_KP_INSERT none XK_KP_0
-BX_KEY_KP_INSERT none XK_KP_Insert
-BX_KEY_KP_LEFT none XK_KP_4
-BX_KEY_KP_LEFT none XK_KP_Left
-BX_KEY_KP_MULTIPLY none XK_KP_Multiply
-BX_KEY_KP_PAGE_DOWN none XK_KP_3
-BX_KEY_KP_PAGE_DOWN none XK_KP_Page_Down
-BX_KEY_KP_PAGE_UP none XK_KP_9
-BX_KEY_KP_PAGE_UP none XK_KP_Page_Up
-BX_KEY_KP_RIGHT none XK_KP_6
-BX_KEY_KP_RIGHT none XK_KP_Right
-BX_KEY_KP_SUBTRACT none XK_KP_Subtract
-BX_KEY_KP_UP none XK_KP_8
-BX_KEY_KP_UP none XK_KP_Up
-BX_KEY_LEFT none XK_Left
-BX_KEY_LEFT_BRACKET+BX_KEY_SHIFT_L '{' XK_braceleft
-BX_KEY_LEFT_BRACKET '[' XK_bracketleft
-BX_KEY_MENU none XK_Menu
-BX_KEY_MINUS '-' XK_minus
-BX_KEY_MINUS+BX_KEY_SHIFT_L '_' XK_underscore
-BX_KEY_NUM_LOCK none XK_Num_Lock
-BX_KEY_PAGE_DOWN none XK_Page_Down
-BX_KEY_PAGE_UP none XK_Page_Up
-BX_KEY_PAUSE none XK_Break
-BX_KEY_PAUSE none XK_Pause
-BX_KEY_PERIOD+BX_KEY_SHIFT_L '>' XK_greater
-BX_KEY_PERIOD '.' XK_period
-BX_KEY_PRINT none XK_Print
-BX_KEY_PRINT none XK_Sys_Req
-BX_KEY_RIGHT none XK_Right
-BX_KEY_RIGHT_BRACKET+BX_KEY_SHIFT_L '}' XK_braceright
-BX_KEY_RIGHT_BRACKET ']' XK_bracketright
-BX_KEY_SCRL_LOCK none XK_Scroll_Lock
-BX_KEY_SEMICOLON+BX_KEY_SHIFT_L ':' XK_colon
-BX_KEY_SEMICOLON ';' XK_semicolon
-BX_KEY_SHIFT_L none XK_Shift_L
-BX_KEY_SHIFT_R none XK_Shift_R
-BX_KEY_SINGLE_QUOTE apostrophe XK_apostrophe
-BX_KEY_SINGLE_QUOTE+BX_KEY_SHIFT_L '"' XK_quotedbl
-BX_KEY_SLASH+BX_KEY_SHIFT_L '?' XK_question
-BX_KEY_SLASH '/' XK_slash
-BX_KEY_SPACE space XK_space
-BX_KEY_TAB none XK_ISO_Left_Tab
-BX_KEY_TAB tab XK_Tab
-BX_KEY_UP none XK_Up
-BX_KEY_WIN_L none XK_Super_L
-BX_KEY_WIN_R none XK_Super_R
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: nogui.cc,v 1.21 2003/06/28 08:04:31 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2001 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-
-// Define BX_PLUGGABLE in files that can be compiled into plugins. For
-// platforms that require a special tag on exported symbols, BX_PLUGGABLE
-// is used to know when we are exporting symbols and when we are importing.
-#define BX_PLUGGABLE
-
-#include "bochs.h"
-#include "icon_bochs.h"
-
-class bx_nogui_gui_c : public bx_gui_c {
-public:
- bx_nogui_gui_c (void) {}
- DECLARE_GUI_VIRTUAL_METHODS()
-};
-
-// declare one instance of the gui object and call macro to insert the
-// plugin code
-static bx_nogui_gui_c *theGui = NULL;
-IMPLEMENT_GUI_PLUGIN_CODE(nogui)
-
-#define LOG_THIS theGui->
-
-// This file defines stubs for the GUI interface, which is a
-// place to start if you want to port bochs to a platform, for
-// which there is no support for your native GUI, or if you want to compile
-// bochs without any native GUI support (no output window or
-// keyboard input will be possible).
-// Look in 'x.cc', 'beos.cc', and 'win32.cc' for specific
-// implementations of this interface. -Kevin
-
-
-
-// ::SPECIFIC_INIT()
-//
-// Called from gui.cc, once upon program startup, to allow for the
-// specific GUI code (X11, BeOS, ...) to be initialized.
-//
-// argc, argv: not used right now, but the intention is to pass native GUI
-// specific options from the command line. (X11 options, BeOS options,...)
-//
-// tilewidth, tileheight: for optimization, graphics_tile_update() passes
-// only updated regions of the screen to the gui code to be redrawn.
-// These define the dimensions of a region (tile).
-// headerbar_y: A headerbar (toolbar) is display on the top of the
-// VGA window, showing floppy status, and other information. It
-// always assumes the width of the current VGA mode width, but
-// it's height is defined by this parameter.
-
- void
-bx_nogui_gui_c::specific_init(int argc, char **argv, unsigned tilewidth, unsigned tileheight,
- unsigned headerbar_y)
-{
- put("NGUI");
- UNUSED(argc);
- UNUSED(argv);
- UNUSED(tilewidth);
- UNUSED(tileheight);
- UNUSED(headerbar_y);
-
- UNUSED(bochs_icon_bits); // global variable
-
- if (bx_options.Oprivate_colormap->get ()) {
- BX_INFO(("private_colormap option ignored."));
- }
-}
-
-
-// ::HANDLE_EVENTS()
-//
-// Called periodically (vga_update_interval in .bochsrc) so the
-// the gui code can poll for keyboard, mouse, and other
-// relevant events.
-
- void
-bx_nogui_gui_c::handle_events(void)
-{
-}
-
-
-// ::FLUSH()
-//
-// Called periodically, requesting that the gui code flush all pending
-// screen update requests.
-
- void
-bx_nogui_gui_c::flush(void)
-{
-}
-
-
-// ::CLEAR_SCREEN()
-//
-// Called to request that the VGA region is cleared. Don't
-// clear the area that defines the headerbar.
-
- void
-bx_nogui_gui_c::clear_screen(void)
-{
-}
-
-
-
-// ::TEXT_UPDATE()
-//
-// Called in a VGA text mode, to update the screen with
-// new content.
-//
-// old_text: array of character/attributes making up the contents
-// of the screen from the last call. See below
-// new_text: array of character/attributes making up the current
-// contents, which should now be displayed. See below
-//
-// format of old_text & new_text: each is 4000 bytes long.
-// This represents 80 characters wide by 25 high, with
-// each character being 2 bytes. The first by is the
-// character value, the second is the attribute byte.
-// I currently don't handle the attribute byte.
-//
-// cursor_x: new x location of cursor
-// cursor_y: new y location of cursor
-
- void
-bx_nogui_gui_c::text_update(Bit8u *old_text, Bit8u *new_text,
- unsigned long cursor_x, unsigned long cursor_y,
- bx_vga_tminfo_t tm_info, unsigned nrows)
-{
- UNUSED(old_text);
- UNUSED(new_text);
- UNUSED(cursor_x);
- UNUSED(cursor_y);
- UNUSED(tm_info);
- UNUSED(nrows);
-}
-
- int
-bx_nogui_gui_c::get_clipboard_text(Bit8u **bytes, Bit32s *nbytes)
-{
- UNUSED(bytes);
- UNUSED(nbytes);
- return 0;
-}
-
- int
-bx_nogui_gui_c::set_clipboard_text(char *text_snapshot, Bit32u len)
-{
- UNUSED(text_snapshot);
- UNUSED(len);
- return 0;
-}
-
-
-// ::PALETTE_CHANGE()
-//
-// Allocate a color in the native GUI, for this color, and put
-// it in the colormap location 'index'.
-// returns: 0=no screen update needed (color map change has direct effect)
-// 1=screen updated needed (redraw using current colormap)
-
- bx_bool
-bx_nogui_gui_c::palette_change(unsigned index, unsigned red, unsigned green, unsigned blue)
-{
- UNUSED(index);
- UNUSED(red);
- UNUSED(green);
- UNUSED(blue);
- return(0);
-}
-
-
-// ::GRAPHICS_TILE_UPDATE()
-//
-// Called to request that a tile of graphics be drawn to the
-// screen, since info in this region has changed.
-//
-// tile: array of 8bit values representing a block of pixels with
-// dimension equal to the 'tilewidth' & 'tileheight' parameters to
-// ::specific_init(). Each value specifies an index into the
-// array of colors you allocated for ::palette_change()
-// x0: x origin of tile
-// y0: y origin of tile
-//
-// note: origin of tile and of window based on (0,0) being in the upper
-// left of the window.
-
- void
-bx_nogui_gui_c::graphics_tile_update(Bit8u *tile, unsigned x0, unsigned y0)
-{
- UNUSED(tile);
- UNUSED(x0);
- UNUSED(y0);
-}
-
-
-
-// ::DIMENSION_UPDATE()
-//
-// Called when the VGA mode changes it's X,Y dimensions.
-// Resize the window to this size, but you need to add on
-// the height of the headerbar to the Y value.
-//
-// x: new VGA x size
-// y: new VGA y size (add headerbar_y parameter from ::specific_init().
-// fheight: new VGA character height in text mode
-// fwidth : new VGA character width in text mode
-// bpp : bits per pixel in graphics mode
-
- void
-bx_nogui_gui_c::dimension_update(unsigned x, unsigned y, unsigned fheight, unsigned fwidth, unsigned bpp)
-{
- UNUSED(x);
- UNUSED(y);
- UNUSED(fheight);
- UNUSED(fwidth);
- UNUSED(bpp);
-}
-
-
-// ::CREATE_BITMAP()
-//
-// Create a monochrome bitmap of size 'xdim' by 'ydim', which will
-// be drawn in the headerbar. Return an integer ID to the bitmap,
-// with which the bitmap can be referenced later.
-//
-// bmap: packed 8 pixels-per-byte bitmap. The pixel order is:
-// bit0 is the left most pixel, bit7 is the right most pixel.
-// xdim: x dimension of bitmap
-// ydim: y dimension of bitmap
-
- unsigned
-bx_nogui_gui_c::create_bitmap(const unsigned char *bmap, unsigned xdim, unsigned ydim)
-{
- UNUSED(bmap);
- UNUSED(xdim);
- UNUSED(ydim);
- return(0);
-}
-
-
-// ::HEADERBAR_BITMAP()
-//
-// Called to install a bitmap in the bochs headerbar (toolbar).
-//
-// bmap_id: will correspond to an ID returned from
-// ::create_bitmap(). 'alignment' is either BX_GRAVITY_LEFT
-// or BX_GRAVITY_RIGHT, meaning install the bitmap in the next
-// available leftmost or rightmost space.
-// alignment: is either BX_GRAVITY_LEFT or BX_GRAVITY_RIGHT,
-// meaning install the bitmap in the next
-// available leftmost or rightmost space.
-// f: a 'C' function pointer to callback when the mouse is clicked in
-// the boundaries of this bitmap.
-
- unsigned
-bx_nogui_gui_c::headerbar_bitmap(unsigned bmap_id, unsigned alignment, void (*f)(void))
-{
- UNUSED(bmap_id);
- UNUSED(alignment);
- UNUSED(f);
- return(0);
-}
-
-
-// ::SHOW_HEADERBAR()
-//
-// Show (redraw) the current headerbar, which is composed of
-// currently installed bitmaps.
-
- void
-bx_nogui_gui_c::show_headerbar(void)
-{
-}
-
-
-// ::REPLACE_BITMAP()
-//
-// Replace the bitmap installed in the headerbar ID slot 'hbar_id',
-// with the one specified by 'bmap_id'. 'bmap_id' will have
-// been generated by ::create_bitmap(). The old and new bitmap
-// must be of the same size. This allows the bitmap the user
-// sees to change, when some action occurs. For example when
-// the user presses on the floppy icon, it then displays
-// the ejected status.
-//
-// hbar_id: headerbar slot ID
-// bmap_id: bitmap ID
-
- void
-bx_nogui_gui_c::replace_bitmap(unsigned hbar_id, unsigned bmap_id)
-{
- UNUSED(hbar_id);
- UNUSED(bmap_id);
-}
-
-
-// ::EXIT()
-//
-// Called before bochs terminates, to allow for a graceful
-// exit from the native GUI mechanism.
-
- void
-bx_nogui_gui_c::exit(void)
-{
- BX_INFO(("bx_nogui_gui_c::exit() not implemented yet."));
-}
-
- void
-bx_nogui_gui_c::mouse_enabled_changed_specific (bx_bool val)
-{
-}
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: rfb.cc,v 1.26.2.1 2004/02/02 22:35:30 cbothamy Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2000 Psyon.Org!
-//
-// Donald Becker
-// http://www.psyon.org
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-// Define BX_PLUGGABLE in files that can be compiled into plugins. For
-// platforms that require a special tag on exported symbols, BX_PLUGGABLE
-// is used to know when we are exporting symbols and when we are importing.
-#define BX_PLUGGABLE
-
-#include "bochs.h"
-#if BX_WITH_RFB
-
-#include "icon_bochs.h"
-#include "font/vga.bitmap.h"
-
-class bx_rfb_gui_c : public bx_gui_c {
-public:
- bx_rfb_gui_c (void) {}
- DECLARE_GUI_VIRTUAL_METHODS()
-};
-
-// declare one instance of the gui object and call macro to insert the
-// plugin code
-static bx_rfb_gui_c *theGui = NULL;
-IMPLEMENT_GUI_PLUGIN_CODE(rfb)
-
-#define LOG_THIS theGui->
-
-#ifdef WIN32
-
-#include <winsock.h>
-#include <process.h>
-#include "rfb.h"
-
-#else
-
-#include <sys/socket.h>
-#include <netinet/tcp.h>
-#include <netinet/in.h>
-#include <unistd.h>
-#include <sys/errno.h>
-#include <pthread.h>
-typedef unsigned long CARD32;
-typedef unsigned short CARD16;
-typedef short INT16;
-typedef unsigned char CARD8;
-typedef int SOCKET;
-
-#endif
-
-#include "rfbproto.h"
-
-static bool keep_alive;
-static bool client_connected;
-
-#define BX_RFB_PORT_MIN 5900
-#define BX_RFB_PORT_MAX 5949
-static unsigned short rfbPort;
-
-// Headerbar stuff
-unsigned rfbBitmapCount = 0;
-struct {
- char *bmap;
- unsigned xdim;
- unsigned ydim;
-} rfbBitmaps[BX_MAX_PIXMAPS];
-
-unsigned rfbHeaderbarBitmapCount = 0;
-struct {
- unsigned int index;
- unsigned int xorigin;
- unsigned int yorigin;
- unsigned int alignment;
- void (*f)(void);
-} rfbHeaderbarBitmaps[BX_MAX_HEADERBAR_ENTRIES];
-
-//Keyboard stuff
-#define KEYBOARD true
-#define MOUSE false
-#define MAX_KEY_EVENTS 512
-struct {
- bool type;
- int key;
- int down;
- int x;
- int y;
-} rfbKeyboardEvent[MAX_KEY_EVENTS];
-static unsigned long rfbKeyboardEvents = 0;
-static bool bKeyboardInUse = false;
-
-// Misc Stuff
-struct {
- unsigned int x;
- unsigned int y;
- unsigned int width;
- unsigned int height;
- bool updated;
-} rfbUpdateRegion;
-
-static char *rfbScreen;
-static char rfbPallet[256];
-
-static long rfbDimensionX, rfbDimensionY;
-static long rfbStretchedX, rfbStretchedY;
-static long rfbHeaderbarY;
-static long rfbTileX = 0;
-static long rfbTileY = 0;
-static unsigned long rfbCursorX = 0;
-static unsigned long rfbCursorY = 0;
-static unsigned long rfbOriginLeft = 0;
-static unsigned long rfbOriginRight = 0;
-
-static unsigned int text_rows=25, text_cols=80;
-static unsigned int font_height=16, font_width=8;
-
-//static unsigned long ServerThread = 0;
-//static unsigned long ServerThreadID = 0;
-
-static SOCKET sGlobal;
-
-void ServerThreadInit(void *indata);
-void HandleRfbClient(SOCKET sClient);
-int ReadExact(int sock, char *buf, int len);
-int WriteExact(int sock, char *buf, int len);
-void DrawBitmap(int x, int y, int width, int height, char *bmap, char color, bool update_client);
-void DrawChar(int x, int y, int width, int height, int fonty, char *bmap, char color);
-void UpdateScreen(unsigned char *newBits, int x, int y, int width, int height, bool update_client);
-void SendUpdate(int x, int y, int width, int height);
-void StartThread();
-void rfbKeyPressed(Bit32u key, int press_release);
-void rfbMouseMove(int x, int y, int bmask);
-void DrawColorPallet();
-
-static const rfbPixelFormat BGR233Format = {
- 8, 8, 1, 1, 7, 7, 3, 0, 3, 6
-};
-
-// Set this for the endian of your machine. 0 = big, 1 = little
-static const int rfbEndianTest = 1;
-
-#define Swap16(s) ((((s) & 0xff) << 8) | (((s) >> 8) & 0xff))
-#define Swap32(l) (((l) >> 24) | (((l) & 0x00ff0000) >> 8) | (((l) & 0x0000ff00) << 8) | ((l) << 24))
-#define Swap16IfLE(s) (*(const char *)&rfbEndianTest ? Swap16(s) : (s))
-#define Swap32IfLE(l) (*(const char *)&rfbEndianTest ? Swap32(l) : (l))
-#define PF_EQ(x,y) ((x.bitsPerPixel == y.bitsPerPixel) && (x.depth == y.depth) && (x.trueColour == y.trueColour) && ((x.bigEndian == y.bigEndian) || (x.bitsPerPixel == 8)) && (!x.trueColour || ((x.redMax == y.redMax) && (x.greenMax == y.greenMax) && (x.blueMax == y.blueMax) && (x.redShift == y.redShift) && (x.greenShift == y.greenShift) && (x.blueShift == y.blueShift))))
-
-// This file defines stubs for the GUI interface, which is a
-// place to start if you want to port bochs to a platform, for
-// which there is no support for your native GUI, or if you want to compile
-// bochs without any native GUI support (no output window or
-// keyboard input will be possible).
-// Look in 'x.cc', 'beos.cc', and 'win32.cc' for specific
-// implementations of this interface. -Kevin
-
-
-// ::SPECIFIC_INIT()
-//
-// Called from gui.cc, once upon program startup, to allow for the
-// specific GUI code (X11, BeOS, ...) to be initialized.
-//
-// argc, argv: not used right now, but the intention is to pass native GUI
-// specific options from the command line. (X11 options, BeOS options,...)
-//
-// tilewidth, tileheight: for optimization, graphics_tile_update() passes
-// only updated regions of the screen to the gui code to be redrawn.
-// These define the dimensions of a region (tile).
-// headerbar_y: A headerbar (toolbar) is display on the top of the
-// VGA window, showing floppy status, and other information. It
-// always assumes the width of the current VGA mode width, but
-// it's height is defined by this parameter.
-
-void bx_rfb_gui_c::specific_init(int argc, char **argv, unsigned tilewidth, unsigned tileheight, unsigned headerbar_y)
-{
- unsigned char fc, vc;
-
- put("RFB");
- UNUSED(bochs_icon_bits);
-
- // the ask menu doesn't work on the client side
- io->set_log_action(LOGLEV_PANIC, ACT_FATAL);
-
- rfbHeaderbarY = headerbar_y;
- rfbDimensionX = 640;
- rfbDimensionY = 480 + rfbHeaderbarY;
- rfbStretchedX = rfbDimensionX;
- rfbStretchedY = rfbDimensionY;
- rfbTileX = tilewidth;
- rfbTileY = tileheight;
-
- for(int i = 0; i < 256; i++) {
- for(int j = 0; j < 16; j++) {
- vc = bx_vgafont[i].data[j];
- fc = 0;
- for (int b = 0; b < 8; b++) {
- fc |= (vc & 0x01) << (7 - b);
- vc >>= 1;
- }
- vga_charmap[i*32+j] = fc;
- }
- }
-
- rfbScreen = (char *)malloc(rfbDimensionX * rfbDimensionY);
- memset(&rfbPallet, 0, sizeof(rfbPallet));
- rfbPallet[63] = (char)0xFF;
-
- rfbUpdateRegion.x = rfbDimensionX;
- rfbUpdateRegion.y = rfbDimensionY;
- rfbUpdateRegion.width = 0;
- rfbUpdateRegion.height = 0;
- rfbUpdateRegion.updated = false;
-
- keep_alive = true;
- client_connected = false;
- StartThread();
-
-#ifdef WIN32
- Sleep(1000);
- SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL);
-#endif
- if (bx_options.Oprivate_colormap->get ()) {
- BX_ERROR(( "private_colormap option ignored." ));
- }
- int counter = 30;
- while ((!client_connected) && (counter--)) {
-#ifdef WIN32
- Sleep(1000);
-#else
- sleep(1);
-#endif
- }
- if (counter < 0) BX_PANIC(("timeout! no client present"));
-}
-
-bool InitWinsock()
-{
-#ifdef WIN32
- WSADATA wsaData;
- if(WSAStartup(MAKEWORD(1,1), &wsaData) != 0) return false;
-#endif
- return true;
-}
-
-bool StopWinsock()
-{
-#ifdef WIN32
- WSACleanup();
-#endif
- return true;
-}
-
-void ServerThreadInit(void *indata)
-{
- SOCKET sServer;
- SOCKET sClient;
- struct sockaddr_in sai;
- unsigned int sai_size;
- int port_ok = 0;
-
-#ifdef WIN32
- SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_IDLE);
-#endif
- if(!InitWinsock()) {
- BX_PANIC(( "could not initialize winsock."));
- goto end_of_thread;
- }
-
- sServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
- if(sServer == -1) {
- BX_PANIC(( "could not create socket." ));
- goto end_of_thread;
- }
- for (rfbPort = BX_RFB_PORT_MIN; rfbPort <= BX_RFB_PORT_MAX; rfbPort++) {
- sai.sin_addr.s_addr = INADDR_ANY;
- sai.sin_family = AF_INET;
- sai.sin_port = htons(rfbPort);
- BX_INFO (("Trying port %d", rfbPort));
- if(bind(sServer, (struct sockaddr *)&sai, sizeof(sai)) == -1) {
- BX_INFO(( "Could not bind socket."));
- continue;
- }
- if(listen(sServer, SOMAXCONN) == -1) {
- BX_INFO(( "Could not listen on socket."));
- continue;
- }
- // success
- port_ok = 1;
- break;
- }
- if (!port_ok) {
- BX_PANIC (("RFB could not bind any port between %d and %d\n",
- BX_RFB_PORT_MIN,
- BX_RFB_PORT_MAX));
- goto end_of_thread;
- }
- BX_INFO (("listening for connections on port %i", rfbPort));
- fprintf (stderr, "RFB: listening for connections on port %i\n", rfbPort);
- sai_size = sizeof(sai);
- while(keep_alive) {
- sClient = accept(sServer, (struct sockaddr *)&sai, (socklen_t*)&sai_size);
- if(sClient != -1) {
- HandleRfbClient(sClient);
- sGlobal = -1;
- close(sClient);
- } else {
- close(sClient);
- }
- }
-
-end_of_thread:
- StopWinsock();
-}
-
-void HandleRfbClient(SOCKET sClient)
-{
- char rfbName[] = "Bochs-RFB";
- rfbProtocolVersionMsg pv;
- int one = 1;
- CARD32 auth;
- rfbClientInitMsg cim;
- rfbServerInitMsg sim;
-
- client_connected = true;
- setsockopt(sClient, IPPROTO_TCP, TCP_NODELAY, (const char *)&one, sizeof(one));
- fprintf(stderr, "# RFB: accepted client connection.\n");
- sprintf(pv, rfbProtocolVersionFormat, rfbProtocolMajorVersion, rfbProtocolMinorVersion);
-
- if(WriteExact(sClient, pv, sz_rfbProtocolVersionMsg) < 0) {
- fprintf(stderr, "# ERROR: RFB: could not send protocol version.\n");
- return;
- }
- if(ReadExact(sClient, pv, sz_rfbProtocolVersionMsg) < 0) {
- fprintf(stderr, "# ERROR: RFB: could not recieve client protocol version.\n");
- return;
- }
-
- auth = Swap32IfLE(rfbNoAuth);
- if(WriteExact(sClient, (char *)&auth, sizeof(auth)) < 0) {
- fprintf(stderr, "# ERROR: RFB: could not send authorization method.\n");
- return;
- }
-
- if(ReadExact(sClient, (char *)&cim, sz_rfbClientInitMsg) < 0) {
- fprintf(stderr, "# ERROR: RFB: could not recieve client initialization message.\n");
- return;
- }
-
- sim.framebufferWidth = Swap16IfLE((short)rfbDimensionX);
- sim.framebufferHeight = Swap16IfLE((short)rfbDimensionY);
- sim.format = BGR233Format;
- sim.format.redMax = Swap16IfLE(sim.format.redMax);
- sim.format.greenMax = Swap16IfLE(sim.format.greenMax);
- sim.format.blueMax = Swap16IfLE(sim.format.blueMax);
- sim.nameLength = strlen(rfbName);
- sim.nameLength = Swap32IfLE(sim.nameLength);
- if(WriteExact(sClient, (char *)&sim, sz_rfbServerInitMsg) < 0) {
- fprintf(stderr, "# ERROR: RFB: could send server initialization message.\n");
- return;
- }
- if(WriteExact(sClient, rfbName, strlen(rfbName)) < 0) {
- fprintf(stderr, "# ERROR: RFB: could not send server name.\n");
- return;
- }
-
- sGlobal = sClient;
- while(keep_alive) {
- CARD8 msgType;
- int n;
-
- if((n = recv(sClient, (char *)&msgType, 1, MSG_PEEK)) <= 0) {
- if(n == 0) {
- fprintf(stderr, "# RFB: client closed connection.\n");
- } else {
- fprintf(stderr, "# RFB: error recieving data.\n");
- }
- return;
- }
-
- switch(msgType) {
- case rfbSetPixelFormat:
- {
- rfbSetPixelFormatMsg spf;
- ReadExact(sClient, (char *)&spf, sizeof(rfbSetPixelFormatMsg));
-
- spf.format.bitsPerPixel = spf.format.bitsPerPixel;
- spf.format.depth = spf.format.depth;
- spf.format.trueColour = (spf.format.trueColour ? 1 : 0);
- spf.format.bigEndian = (spf.format.bigEndian ? 1 : 0);
- spf.format.redMax = Swap16IfLE(spf.format.redMax);
- spf.format.greenMax = Swap16IfLE(spf.format.greenMax);
- spf.format.blueMax = Swap16IfLE(spf.format.blueMax);
- spf.format.redShift = spf.format.redShift;
- spf.format.greenShift = spf.format.greenShift;
- spf.format.blueShift = spf.format.blueShift;
-
- if (!PF_EQ(spf.format, BGR233Format)) {
- fprintf(stderr,"# ERROR: RFB: client has wrong pixel format\n");
- //return;
- }
- break;
- }
- case rfbFixColourMapEntries:
- {
- rfbFixColourMapEntriesMsg fcme;
- ReadExact(sClient, (char *)&fcme, sizeof(rfbFixColourMapEntriesMsg));
- break;
- }
- case rfbSetEncodings:
- {
- rfbSetEncodingsMsg se;
- int i;
- CARD32 enc;
- ReadExact(sClient, (char *)&se, sizeof(rfbSetEncodingsMsg));
- se.nEncodings = Swap16IfLE(se.nEncodings);
- for(i = 0; i < se.nEncodings; i++) {
- if((n = ReadExact(sClient, (char *)&enc, sizeof(CARD32))) <= 0) {
- if(n == 0) {
- fprintf(stderr, "# RFB: client closed connection.\n");
- } else {
- fprintf(stderr, "# RFB: error recieving data.\n");
- }
- return;
- }
- }
- break;
- }
- case rfbFramebufferUpdateRequest:
- {
- rfbFramebufferUpdateRequestMsg fur;
-
- ReadExact(sClient, (char *)&fur, sizeof(rfbFramebufferUpdateRequestMsg));
- if(!fur.incremental) {
- rfbUpdateRegion.x = 0;
- rfbUpdateRegion.y = 0;
- rfbUpdateRegion.width = rfbDimensionX;
- rfbUpdateRegion.height = rfbDimensionY;
- rfbUpdateRegion.updated = true;
- } //else {
- // if(fur.x < rfbUpdateRegion.x) rfbUpdateRegion.x = fur.x;
- // if(fur.y < rfbUpdateRegion.x) rfbUpdateRegion.y = fur.y;
- // if(((fur.x + fur.w) - rfbUpdateRegion.x) > rfbUpdateRegion.width) rfbUpdateRegion.width = ((fur.x + fur.w) - rfbUpdateRegion.x);
- // if(((fur.y + fur.h) - rfbUpdateRegion.y) > rfbUpdateRegion.height) rfbUpdateRegion.height = ((fur.y + fur.h) - rfbUpdateRegion.y);
- //}
- //rfbUpdateRegion.updated = true;
- break;
- }
- case rfbKeyEvent:
- {
- rfbKeyEventMsg ke;
- ReadExact(sClient, (char *)&ke, sizeof(rfbKeyEventMsg));
- ke.key = Swap32IfLE(ke.key);
- while(bKeyboardInUse);
- bKeyboardInUse = true;
- if (rfbKeyboardEvents >= MAX_KEY_EVENTS) break;
- rfbKeyboardEvent[rfbKeyboardEvents].type = KEYBOARD;
- rfbKeyboardEvent[rfbKeyboardEvents].key = ke.key;
- rfbKeyboardEvent[rfbKeyboardEvents].down = ke.down;
- rfbKeyboardEvents++;
- bKeyboardInUse = false;
- break;
- }
- case rfbPointerEvent:
- {
- rfbPointerEventMsg pe;
- ReadExact(sClient, (char *)&pe, sizeof(rfbPointerEventMsg));
- while(bKeyboardInUse);
- bKeyboardInUse = true;
- if (rfbKeyboardEvents >= MAX_KEY_EVENTS) break;
- rfbKeyboardEvent[rfbKeyboardEvents].type = MOUSE;
- rfbKeyboardEvent[rfbKeyboardEvents].x = Swap16IfLE(pe.x);
- rfbKeyboardEvent[rfbKeyboardEvents].y = Swap16IfLE(pe.y);
- rfbKeyboardEvent[rfbKeyboardEvents].down = pe.buttonMask;
- rfbKeyboardEvents++;
- bKeyboardInUse = false;
- break;
- }
- case rfbClientCutText:
- {
- rfbClientCutTextMsg cct;
- ReadExact(sClient, (char *)&cct, sizeof(rfbClientCutTextMsg));
- break;
- }
- }
- }
-}
-// ::HANDLE_EVENTS()
-//
-// Called periodically (vga_update_interval in .bochsrc) so the
-// the gui code can poll for keyboard, mouse, and other
-// relevant events.
-
-void bx_rfb_gui_c::handle_events(void)
-{
- unsigned int i = 0;
- while(bKeyboardInUse);
- bKeyboardInUse = true;
- if(rfbKeyboardEvents > 0) {
- for(i = 0; i < rfbKeyboardEvents; i++) {
- if(rfbKeyboardEvent[i].type == KEYBOARD) {
- rfbKeyPressed(rfbKeyboardEvent[i].key, rfbKeyboardEvent[i].down);
- } else { //type == MOUSE;
- rfbMouseMove(rfbKeyboardEvent[i].x, rfbKeyboardEvent[i].y, rfbKeyboardEvent[i].down);
- }
- }
- rfbKeyboardEvents = 0;
- }
- bKeyboardInUse = false;
-
- if(rfbUpdateRegion.updated) {
- SendUpdate(rfbUpdateRegion.x, rfbUpdateRegion.y, rfbUpdateRegion.width, rfbUpdateRegion.height);
- rfbUpdateRegion.x = rfbDimensionX;
- rfbUpdateRegion.y = rfbDimensionY;
- rfbUpdateRegion.width = 0;
- rfbUpdateRegion.height = 0;
- }
- rfbUpdateRegion.updated = false;
-}
-
-
-// ::FLUSH()
-//
-// Called periodically, requesting that the gui code flush all pending
-// screen update requests.
-
-void bx_rfb_gui_c::flush(void)
-{
-}
-
-
-// ::CLEAR_SCREEN()
-//
-// Called to request that the VGA region is cleared. Don't
-// clear the area that defines the headerbar.
-void bx_rfb_gui_c::clear_screen(void)
-{
- memset(&rfbScreen[rfbDimensionX * rfbHeaderbarY], 0, rfbDimensionX * (rfbDimensionY - rfbHeaderbarY));
-}
-
-
-
-// ::TEXT_UPDATE()
-//
-// Called in a VGA text mode, to update the screen with
-// new content.
-//
-// old_text: array of character/attributes making up the contents
-// of the screen from the last call. See below
-// new_text: array of character/attributes making up the current
-// contents, which should now be displayed. See below
-//
-// format of old_text & new_text: each is 4000 bytes long.
-// This represents 80 characters wide by 25 high, with
-// each character being 2 bytes. The first by is the
-// character value, the second is the attribute byte.
-// I currently don't handle the attribute byte.
-//
-// cursor_x: new x location of cursor
-// cursor_y: new y location of cursor
-
-void bx_rfb_gui_c::text_update(Bit8u *old_text, Bit8u *new_text, unsigned long cursor_x, unsigned long cursor_y, bx_vga_tminfo_t tm_info, unsigned nrows)
-{
- unsigned char *old_line, *new_line;
- unsigned char cAttr, cChar;
- unsigned int curs, hchars, offset, rows, x, y, xc, yc;
- bx_bool force_update=0;
-
- UNUSED(nrows);
-
- if(charmap_updated) {
- force_update = 1;
- charmap_updated = 0;
- }
-
- // first invalidate character at previous and new cursor location
- if ( (rfbCursorY < text_rows) && (rfbCursorX < text_cols) ) {
- curs = rfbCursorY * tm_info.line_offset + rfbCursorX * 2;
- old_text[curs] = ~new_text[curs];
- }
- if((tm_info.cs_start <= tm_info.cs_end) && (tm_info.cs_start < font_height) &&
- (cursor_y < text_rows) && (cursor_x < text_cols)) {
- curs = cursor_y * tm_info.line_offset + cursor_x * 2;
- old_text[curs] = ~new_text[curs];
- } else {
- curs = 0xffff;
- }
-
- rows = text_rows;
- y = 0;
- do {
- hchars = text_cols;
- new_line = new_text;
- old_line = old_text;
- offset = y * tm_info.line_offset;
- yc = y * font_height + rfbHeaderbarY;
- x = 0;
- do {
- if (force_update || (old_text[0] != new_text[0])
- || (old_text[1] != new_text[1])) {
- cChar = new_text[0];
- cAttr = new_text[1];
- xc = x * 8;
- DrawChar(xc, yc, 8, font_height, 0, (char *)&vga_charmap[cChar<<5], cAttr);
- if(yc < rfbUpdateRegion.y) rfbUpdateRegion.y = yc;
- if((yc + font_height - rfbUpdateRegion.y) > rfbUpdateRegion.height) rfbUpdateRegion.height = (yc + font_height - rfbUpdateRegion.y);
- if(xc < rfbUpdateRegion.x) rfbUpdateRegion.x = xc;
- if((xc + 8 - rfbUpdateRegion.x) > rfbUpdateRegion.width) rfbUpdateRegion.width = (xc + 8 - rfbUpdateRegion.x);
- rfbUpdateRegion.updated = true;
- if (offset == curs) {
- cAttr = ((cAttr >> 4) & 0xF) + ((cAttr & 0xF) << 4);
- DrawChar(xc, yc + tm_info.cs_start, 8, tm_info.cs_end - tm_info.cs_start + 1,
- tm_info.cs_start, (char *)&vga_charmap[cChar<<5], cAttr);
- }
- }
- x++;
- new_text+=2;
- old_text+=2;
- offset+=2;
- } while (--hchars);
- y++;
- new_text = new_line + tm_info.line_offset;
- old_text = old_line + tm_info.line_offset;
- } while (--rows);
-
- rfbCursorX = cursor_x;
- rfbCursorY = cursor_y;
-}
-
- int
-bx_rfb_gui_c::get_clipboard_text(Bit8u **bytes, Bit32s *nbytes)
-{
- return 0;
-}
-
- int
-bx_rfb_gui_c::set_clipboard_text(char *text_snapshot, Bit32u len)
-{
- return 0;
-}
-
-
-// ::PALETTE_CHANGE()
-//
-// Allocate a color in the native GUI, for this color, and put
-// it in the colormap location 'index'.
-// returns: 0=no screen update needed (color map change has direct effect)
-// 1=screen updated needed (redraw using current colormap)
-
-bx_bool bx_rfb_gui_c::palette_change(unsigned index, unsigned red, unsigned green, unsigned blue)
-{
- rfbPallet[index] = (((red * 7 + 127) / 255) << 0) | (((green * 7 + 127) / 255) << 3) | (((blue * 3 + 127) / 255) << 6);
- return(1);
-}
-
-
-// ::GRAPHICS_TILE_UPDATE()
-//
-// Called to request that a tile of graphics be drawn to the
-// screen, since info in this region has changed.
-//
-// tile: array of 8bit values representing a block of pixels with
-// dimension equal to the 'tilewidth' & 'tileheight' parameters to
-// ::specific_init(). Each value specifies an index into the
-// array of colors you allocated for ::palette_change()
-// x0: x origin of tile
-// y0: y origin of tile
-//
-// note: origin of tile and of window based on (0,0) being in the upper
-// left of the window.
-void bx_rfb_gui_c::graphics_tile_update(Bit8u *tile, unsigned x0, unsigned y0)
-{
- UpdateScreen(tile, x0, y0 + rfbHeaderbarY, rfbTileX, rfbTileY, false);
- if(x0 < rfbUpdateRegion.x) rfbUpdateRegion.x = x0;
- if((y0 + rfbHeaderbarY) < rfbUpdateRegion.y) rfbUpdateRegion.y = y0 + rfbHeaderbarY;
- if(((y0 + rfbHeaderbarY + rfbTileY) - rfbUpdateRegion.y) > rfbUpdateRegion.height) rfbUpdateRegion.height = ((y0 + rfbHeaderbarY + rfbTileY) - rfbUpdateRegion.y);
- if(((x0 + rfbTileX) - rfbUpdateRegion.x) > rfbUpdateRegion.width) rfbUpdateRegion.width = ((x0 + rfbTileX) - rfbUpdateRegion.x);
- rfbUpdateRegion.updated = true;
-}
-
-
-
-// ::DIMENSION_UPDATE()
-//
-// Called when the VGA mode changes it's X,Y dimensions.
-// Resize the window to this size, but you need to add on
-// the height of the headerbar to the Y value.
-//
-// x: new VGA x size
-// y: new VGA y size (add headerbar_y parameter from ::specific_init().
-// fheight: new VGA character height in text mode
-// fwidth : new VGA character width in text mode
-// bpp : bits per pixel in graphics mode
-
- void
-bx_rfb_gui_c::dimension_update(unsigned x, unsigned y, unsigned fheight, unsigned fwidth, unsigned bpp)
-{
- if (bpp > 8) {
- BX_PANIC(("%d bpp graphics mode not supported yet", bpp));
- }
- if (fheight > 0) {
- font_height = fheight;
- font_width = fwidth;
- text_cols = x / fwidth;
- text_rows = y / fheight;
- } else {
- if ((x > 640) || (y > 480)) {
- BX_PANIC(("dimension_update(): RFB doesn't support graphics modes > 640x480 (%dx%d)", x, y));
- }
- }
-}
-
-
-// ::CREATE_BITMAP()
-//
-// Create a monochrome bitmap of size 'xdim' by 'ydim', which will
-// be drawn in the headerbar. Return an integer ID to the bitmap,
-// with which the bitmap can be referenced later.
-//
-// bmap: packed 8 pixels-per-byte bitmap. The pixel order is:
-// bit0 is the left most pixel, bit7 is the right most pixel.
-// xdim: x dimension of bitmap
-// ydim: y dimension of bitmap
-
-unsigned bx_rfb_gui_c::create_bitmap(const unsigned char *bmap, unsigned xdim, unsigned ydim)
-{
- if(rfbBitmapCount >= BX_MAX_PIXMAPS) {
- fprintf(stderr, "# RFB: too many pixmaps.\n");
- return 0;
- }
- rfbBitmaps[rfbBitmapCount].bmap = (char *)malloc((xdim * ydim) / 8);
- rfbBitmaps[rfbBitmapCount].xdim = xdim;
- rfbBitmaps[rfbBitmapCount].ydim = ydim;
- memcpy(rfbBitmaps[rfbBitmapCount].bmap, bmap, (xdim * ydim) / 8);
-
- rfbBitmapCount++;
- return(rfbBitmapCount - 1);
-}
-
-
-// ::HEADERBAR_BITMAP()
-//
-// Called to install a bitmap in the bochs headerbar (toolbar).
-//
-// bmap_id: will correspond to an ID returned from
-// ::create_bitmap(). 'alignment' is either BX_GRAVITY_LEFT
-// or BX_GRAVITY_RIGHT, meaning install the bitmap in the next
-// available leftmost or rightmost space.
-// alignment: is either BX_GRAVITY_LEFT or BX_GRAVITY_RIGHT,
-// meaning install the bitmap in the next
-// available leftmost or rightmost space.
-// f: a 'C' function pointer to callback when the mouse is clicked in
-// the boundaries of this bitmap.
-
-unsigned bx_rfb_gui_c::headerbar_bitmap(unsigned bmap_id, unsigned alignment, void (*f)(void))
-{
- int hb_index;
-
- if((rfbHeaderbarBitmapCount + 1) > BX_MAX_HEADERBAR_ENTRIES) {
- return 0;
- }
-
- rfbHeaderbarBitmapCount++;
- hb_index = rfbHeaderbarBitmapCount - 1;
- rfbHeaderbarBitmaps[hb_index].index = bmap_id;
- rfbHeaderbarBitmaps[hb_index].alignment = alignment;
- rfbHeaderbarBitmaps[hb_index].f = f;
- if (alignment == BX_GRAVITY_LEFT) {
- rfbHeaderbarBitmaps[hb_index].xorigin = rfbOriginLeft;
- rfbHeaderbarBitmaps[hb_index].yorigin = 0;
- rfbOriginLeft += rfbBitmaps[bmap_id].xdim;
- } else { // BX_GRAVITY_RIGHT
- rfbOriginRight += rfbBitmaps[bmap_id].xdim;
- rfbHeaderbarBitmaps[hb_index].xorigin = rfbOriginRight;
- rfbHeaderbarBitmaps[hb_index].yorigin = 0;
- }
- return hb_index;
-}
-
-
-// ::SHOW_HEADERBAR()
-//
-// Show (redraw) the current headerbar, which is composed of
-// currently installed bitmaps.
-
-void bx_rfb_gui_c::show_headerbar(void)
-{
- char *newBits;
- unsigned int i, xorigin;
-
- newBits = (char *)malloc(rfbDimensionX * rfbHeaderbarY);
- memset(newBits, 0, (rfbDimensionX * rfbHeaderbarY));
- DrawBitmap(0, 0, rfbDimensionX, rfbHeaderbarY, newBits, (char)0xf0, false);
- for(i = 0; i < rfbHeaderbarBitmapCount; i++) {
- if(rfbHeaderbarBitmaps[i].alignment == BX_GRAVITY_LEFT) {
- xorigin = rfbHeaderbarBitmaps[i].xorigin;
- } else {
- xorigin = rfbDimensionX - rfbHeaderbarBitmaps[i].xorigin;
- }
- DrawBitmap(xorigin, 0, rfbBitmaps[rfbHeaderbarBitmaps[i].index].xdim, rfbBitmaps[rfbHeaderbarBitmaps[i].index].ydim, rfbBitmaps[rfbHeaderbarBitmaps[i].index].bmap, (char)0xf0, false);
- }
- free(newBits);
-}
-
-
-// ::REPLACE_BITMAP()
-//
-// Replace the bitmap installed in the headerbar ID slot 'hbar_id',
-// with the one specified by 'bmap_id'. 'bmap_id' will have
-// been generated by ::create_bitmap(). The old and new bitmap
-// must be of the same size. This allows the bitmap the user
-// sees to change, when some action occurs. For example when
-// the user presses on the floppy icon, it then displays
-// the ejected status.
-//
-// hbar_id: headerbar slot ID
-// bmap_id: bitmap ID
-
-void bx_rfb_gui_c::replace_bitmap(unsigned hbar_id, unsigned bmap_id)
-{
- rfbHeaderbarBitmaps[hbar_id].index = bmap_id;
-}
-
-
-// ::EXIT()
-//
-// Called before bochs terminates, to allow for a graceful
-// exit from the native GUI mechanism.
-void bx_rfb_gui_c::exit(void)
-{
- unsigned int i;
- keep_alive = false;
- StopWinsock();
- free(rfbScreen);
- for(i = 0; i < rfbBitmapCount; i++) {
- free(rfbBitmaps[i].bmap);
- }
- fprintf(stderr, "# RFB: bx_rfb_gui_c::exit()\n");
-}
-
-/*
-* ReadExact reads an exact number of bytes on a TCP socket. Returns 1 if
-* those bytes have been read, 0 if the other end has closed, or -1 if an error
-* occurred (errno is set to ETIMEDOUT if it timed out).
-*/
-
-int ReadExact(int sock, char *buf, int len)
-{
- int n;
-
- while (len > 0) {
- n = recv(sock, buf, len, 0);
- if (n > 0) {
- buf += n;
- len -= n;
- } else {
- return n;
- }
- }
- return 1;
-}
-
-/*
-* WriteExact writes an exact number of bytes on a TCP socket. Returns 1 if
-* those bytes have been written, or -1 if an error occurred (errno is set to
-* ETIMEDOUT if it timed out).
-*/
-
-int WriteExact(int sock, char *buf, int len)
-{
- int n;
-
- while (len > 0) {
- n = send(sock, buf, len,0);
-
- if (n > 0) {
- buf += n;
- len -= n;
- } else if (n == 0) {
- fprintf(stderr,"WriteExact: write returned 0?\n");
- return n;
- } else {
- return n;
- }
- }
- return 1;
-}
-
-void DrawBitmap(int x, int y, int width, int height, char *bmap, char color, bool update_client)
-{
- int i;
- unsigned char *newBits;
- char fgcolor, bgcolor;
- char vgaPallet[] = { (char)0x00, //Black
- (char)0x01, //Dark Blue
- (char)0x02, //Dark Green
- (char)0x03, //Dark Cyan
- (char)0x04, //Dark Red
- (char)0x05, //Dark Magenta
- (char)0x06, //Brown
- (char)0x07, //Light Gray
- (char)0x38, //Dark Gray
- (char)0x09, //Light Blue
- (char)0x12, //Green
- (char)0x1B, //Cyan
- (char)0x24, //Light Red
- (char)0x2D, //Magenta
- (char)0x36, //Yellow
- (char)0x3F //White
- };
-
- bgcolor = vgaPallet[(color >> 4) & 0xF];
- fgcolor = vgaPallet[color & 0xF];
- newBits = (unsigned char *)malloc(width * height);
- memset(newBits, 0, (width * height));
- for(i = 0; i < (width * height) / 8; i++) {
- newBits[i * 8 + 0] = (bmap[i] & 0x01) ? fgcolor : bgcolor;
- newBits[i * 8 + 1] = (bmap[i] & 0x02) ? fgcolor : bgcolor;
- newBits[i * 8 + 2] = (bmap[i] & 0x04) ? fgcolor : bgcolor;
- newBits[i * 8 + 3] = (bmap[i] & 0x08) ? fgcolor : bgcolor;
- newBits[i * 8 + 4] = (bmap[i] & 0x10) ? fgcolor : bgcolor;
- newBits[i * 8 + 5] = (bmap[i] & 0x20) ? fgcolor : bgcolor;
- newBits[i * 8 + 6] = (bmap[i] & 0x40) ? fgcolor : bgcolor;
- newBits[i * 8 + 7] = (bmap[i] & 0x80) ? fgcolor : bgcolor;
- }
- UpdateScreen(newBits, x, y, width, height, update_client);
- //DrawColorPallet();
- free(newBits);
-}
-
-void DrawChar(int x, int y, int width, int height, int fonty, char *bmap, char color)
-{
- static unsigned char newBits[8 * 32];
- unsigned char mask;
- int bytes = width * height;
- char fgcolor, bgcolor;
- char vgaPallet[] = { (char)0x00, //Black
- (char)0x01, //Dark Blue
- (char)0x02, //Dark Green
- (char)0x03, //Dark Cyan
- (char)0x04, //Dark Red
- (char)0x05, //Dark Magenta
- (char)0x06, //Brown
- (char)0x07, //Light Gray
- (char)0x38, //Dark Gray
- (char)0x09, //Light Blue
- (char)0x12, //Green
- (char)0x1B, //Cyan
- (char)0x24, //Light Red
- (char)0x2D, //Magenta
- (char)0x36, //Yellow
- (char)0x3F //White
- };
-
- bgcolor = vgaPallet[(color >> 4) & 0xF];
- fgcolor = vgaPallet[color & 0xF];
-
- for(int i = 0; i < bytes; i+=width) {
- mask = 0x80;
- for(int j = 0; j < width; j++) {
- newBits[i + j] = (bmap[fonty] & mask) ? fgcolor : bgcolor;
- mask >>= 1;
- }
- fonty++;
- }
- UpdateScreen(newBits, x, y, width, height, false);
- //DrawColorPallet();
-}
-
-void DrawColorPallet()
-{
- unsigned char bits[100];
- int x = 0, y = 0, c;
- for(c = 0; c < 256; c++) {
- memset(&bits, rfbPallet[c], 100);
- UpdateScreen(bits, x, y, 10, 10, false);
- x += 10;
- if(x > 70) {
- y += 10;
- x = 0;
- }
- }
-}
-
-void UpdateScreen(unsigned char *newBits, int x, int y, int width, int height, bool update_client)
-{
- int i, c;
- for(i = 0; i < height; i++) {
- for(c = 0; c < width; c++) {
- newBits[(i * width) + c] = rfbPallet[newBits[(i * width) + c]];
- }
- memcpy(&rfbScreen[y * rfbDimensionX + x], &newBits[i * width], width);
- y++;
- }
- if(update_client) {
- if(sGlobal == -1) return;
- rfbFramebufferUpdateMsg fum;
- rfbFramebufferUpdateRectHeader furh;
- fum.type = rfbFramebufferUpdate;
- fum.nRects = Swap16IfLE(1);
- WriteExact(sGlobal, (char *)&fum, sz_rfbFramebufferUpdateMsg);
- furh.r.x = Swap16IfLE(x);
- furh.r.y = Swap16IfLE((y - i));
- furh.r.w = Swap16IfLE((short)width);
- furh.r.h = Swap16IfLE((short)height);
- furh.encoding = Swap32IfLE(rfbEncodingRaw);
- WriteExact(sGlobal, (char *)&furh, sz_rfbFramebufferUpdateRectHeader);
- WriteExact(sGlobal, (char *)newBits, width * height);
- }
-}
-
-void SendUpdate(int x, int y, int width, int height)
-{
- char *newBits;
- int i;
-
- if(x < 0 || y < 0 || (x + width) > rfbDimensionX || (y + height) > rfbDimensionY) {
- fprintf(stderr, "# RFB: Dimensions out of bounds. x=%i y=%i w=%i h=%i\n", x, y, width, height);
- }
- if(sGlobal != -1) {
- rfbFramebufferUpdateMsg fum;
- rfbFramebufferUpdateRectHeader furh;
-
- fum.type = rfbFramebufferUpdate;
- fum.nRects = Swap16IfLE(1);
-
- furh.r.x = Swap16IfLE(x);
- furh.r.y = Swap16IfLE(y);
- furh.r.w = Swap16IfLE((short)width);
- furh.r.h = Swap16IfLE((short)height);
- furh.encoding = Swap32IfLE(rfbEncodingRaw);
-
- newBits = (char *)malloc(width * height);
- for(i = 0; i < height; i++) {
- memcpy(&newBits[i * width], &rfbScreen[y * rfbDimensionX + x], width);
- y++;
- }
-
- WriteExact(sGlobal, (char *)&fum, sz_rfbFramebufferUpdateMsg);
- WriteExact(sGlobal, (char *)&furh, sz_rfbFramebufferUpdateRectHeader);
- WriteExact(sGlobal, (char *)newBits, width * height);
-
- free(newBits);
- }
-}
-
-void StartThread()
-{
-#ifdef WIN32
- _beginthread(ServerThreadInit, 0, NULL);
-#else
- pthread_t thread;
- pthread_create(&thread, NULL, (void *(*)(void *))&ServerThreadInit, NULL);
-#endif
-}
-
-/***********************/
-/* Keyboard Definitons */
-/* And */
-/* Functions */
-/***********************/
-
-#define XK_space 0x020
-#define XK_asciitilde 0x07e
-
-#define XK_dead_grave 0xFE50
-#define XK_dead_acute 0xFE51
-#define XK_dead_circumflex 0xFE52
-#define XK_dead_tilde 0xFE53
-
-#define XK_BackSpace 0xFF08
-#define XK_Tab 0xFF09
-#define XK_Linefeed 0xFF0A
-#define XK_Clear 0xFF0B
-#define XK_Return 0xFF0D
-#define XK_Pause 0xFF13
-#define XK_Scroll_Lock 0xFF14
-#define XK_Sys_Req 0xFF15
-#define XK_Escape 0xFF1B
-
-#define XK_Delete 0xFFFF
-
-#define XK_Home 0xFF50
-#define XK_Left 0xFF51
-#define XK_Up 0xFF52
-#define XK_Right 0xFF53
-#define XK_Down 0xFF54
-#define XK_Page_Up 0xFF55
-#define XK_Page_Down 0xFF56
-#define XK_End 0xFF57
-#define XK_Begin 0xFF58
-
-#define XK_Select 0xFF60
-#define XK_Print 0xFF61
-#define XK_Execute 0xFF62
-#define XK_Insert 0xFF63
-
-#define XK_Cancel 0xFF69
-#define XK_Help 0xFF6A
-#define XK_Break 0xFF6B
-#define XK_Num_Lock 0xFF7F
-
-#define XK_KP_Space 0xFF80
-#define XK_KP_Tab 0xFF89
-#define XK_KP_Enter 0xFF8D
-
-#define XK_KP_Home 0xFF95
-#define XK_KP_Left 0xFF96
-#define XK_KP_Up 0xFF97
-#define XK_KP_Right 0xFF98
-#define XK_KP_Down 0xFF99
-#define XK_KP_Prior 0xFF9A
-#define XK_KP_Page_Up 0xFF9A
-#define XK_KP_Next 0xFF9B
-#define XK_KP_Page_Down 0xFF9B
-#define XK_KP_End 0xFF9C
-#define XK_KP_Begin 0xFF9D
-#define XK_KP_Insert 0xFF9E
-#define XK_KP_Delete 0xFF9F
-#define XK_KP_Equal 0xFFBD
-#define XK_KP_Multiply 0xFFAA
-#define XK_KP_Add 0xFFAB
-#define XK_KP_Separator 0xFFAC
-#define XK_KP_Subtract 0xFFAD
-#define XK_KP_Decimal 0xFFAE
-#define XK_KP_Divide 0xFFAF
-
-#define XK_KP_F1 0xFF91
-#define XK_KP_F2 0xFF92
-#define XK_KP_F3 0xFF93
-#define XK_KP_F4 0xFF94
-
-#define XK_KP_0 0xFFB0
-#define XK_KP_1 0xFFB1
-#define XK_KP_2 0xFFB2
-#define XK_KP_3 0xFFB3
-#define XK_KP_4 0xFFB4
-#define XK_KP_5 0xFFB5
-#define XK_KP_6 0xFFB6
-#define XK_KP_7 0xFFB7
-#define XK_KP_8 0xFFB8
-#define XK_KP_9 0xFFB9
-
-#define XK_F1 0xFFBE
-#define XK_F2 0xFFBF
-#define XK_F3 0xFFC0
-#define XK_F4 0xFFC1
-#define XK_F5 0xFFC2
-#define XK_F6 0xFFC3
-#define XK_F7 0xFFC4
-#define XK_F8 0xFFC5
-#define XK_F9 0xFFC6
-#define XK_F10 0xFFC7
-#define XK_F11 0xFFC8
-#define XK_F12 0xFFC9
-#define XK_F13 0xFFCA
-#define XK_F14 0xFFCB
-#define XK_F15 0xFFCC
-#define XK_F16 0xFFCD
-#define XK_F17 0xFFCE
-#define XK_F18 0xFFCF
-#define XK_F19 0xFFD0
-#define XK_F20 0xFFD1
-#define XK_F21 0xFFD2
-#define XK_F22 0xFFD3
-#define XK_F23 0xFFD4
-#define XK_F24 0xFFD5
-
-
-#define XK_Shift_L 0xFFE1
-#define XK_Shift_R 0xFFE2
-#define XK_Control_L 0xFFE3
-#define XK_Control_R 0xFFE4
-#define XK_Caps_Lock 0xFFE5
-#define XK_Shift_Lock 0xFFE6
-#define XK_Meta_L 0xFFE7
-#define XK_Meta_R 0xFFE8
-#define XK_Alt_L 0xFFE9
-#define XK_Alt_R 0xFFEA
-
-Bit32u rfb_ascii_to_key_event[0x5f] = {
- // !"#$%&'
- BX_KEY_SPACE,
- BX_KEY_1,
- BX_KEY_SINGLE_QUOTE,
- BX_KEY_3,
- BX_KEY_4,
- BX_KEY_5,
- BX_KEY_7,
- BX_KEY_SINGLE_QUOTE,
-
- // ()*+,-./
- BX_KEY_9,
- BX_KEY_0,
- BX_KEY_8,
- BX_KEY_EQUALS,
- BX_KEY_COMMA,
- BX_KEY_MINUS,
- BX_KEY_PERIOD,
- BX_KEY_SLASH,
-
- // 01234567
- BX_KEY_0,
- BX_KEY_1,
- BX_KEY_2,
- BX_KEY_3,
- BX_KEY_4,
- BX_KEY_5,
- BX_KEY_6,
- BX_KEY_7,
-
- // 89:;<=>?
- BX_KEY_8,
- BX_KEY_9,
- BX_KEY_SEMICOLON,
- BX_KEY_SEMICOLON,
- BX_KEY_COMMA,
- BX_KEY_EQUALS,
- BX_KEY_PERIOD,
- BX_KEY_SLASH,
-
- // @ABCDEFG
- BX_KEY_2,
- BX_KEY_A,
- BX_KEY_B,
- BX_KEY_C,
- BX_KEY_D,
- BX_KEY_E,
- BX_KEY_F,
- BX_KEY_G,
-
-
- // HIJKLMNO
- BX_KEY_H,
- BX_KEY_I,
- BX_KEY_J,
- BX_KEY_K,
- BX_KEY_L,
- BX_KEY_M,
- BX_KEY_N,
- BX_KEY_O,
-
-
- // PQRSTUVW
- BX_KEY_P,
- BX_KEY_Q,
- BX_KEY_R,
- BX_KEY_S,
- BX_KEY_T,
- BX_KEY_U,
- BX_KEY_V,
- BX_KEY_W,
-
- // XYZ[\]^_
- BX_KEY_X,
- BX_KEY_Y,
- BX_KEY_Z,
- BX_KEY_LEFT_BRACKET,
- BX_KEY_BACKSLASH,
- BX_KEY_RIGHT_BRACKET,
- BX_KEY_6,
- BX_KEY_MINUS,
-
- // `abcdefg
- BX_KEY_GRAVE,
- BX_KEY_A,
- BX_KEY_B,
- BX_KEY_C,
- BX_KEY_D,
- BX_KEY_E,
- BX_KEY_F,
- BX_KEY_G,
-
- // hijklmno
- BX_KEY_H,
- BX_KEY_I,
- BX_KEY_J,
- BX_KEY_K,
- BX_KEY_L,
- BX_KEY_M,
- BX_KEY_N,
- BX_KEY_O,
-
- // pqrstuvw
- BX_KEY_P,
- BX_KEY_Q,
- BX_KEY_R,
- BX_KEY_S,
- BX_KEY_T,
- BX_KEY_U,
- BX_KEY_V,
- BX_KEY_W,
-
- // xyz{|}~
- BX_KEY_X,
- BX_KEY_Y,
- BX_KEY_Z,
- BX_KEY_LEFT_BRACKET,
- BX_KEY_BACKSLASH,
- BX_KEY_RIGHT_BRACKET,
- BX_KEY_GRAVE
- };
-
-void rfbKeyPressed(Bit32u key, int press_release)
-{
- Bit32u key_event;
-
- if((key >= XK_space) && (key <= XK_asciitilde)) {
- key_event = rfb_ascii_to_key_event[key - XK_space];
- } else {
- switch (key) {
- case XK_KP_1:
-#ifdef XK_KP_End
- case XK_KP_End:
-#endif
- key_event = BX_KEY_KP_END; break;
-
- case XK_KP_2:
-#ifdef XK_KP_Down
- case XK_KP_Down:
-#endif
- key_event = BX_KEY_KP_DOWN; break;
-
- case XK_KP_3:
-#ifdef XK_KP_Page_Down
- case XK_KP_Page_Down:
-#endif
- key_event = BX_KEY_KP_PAGE_DOWN; break;
-
- case XK_KP_4:
-#ifdef XK_KP_Left
- case XK_KP_Left:
-#endif
- key_event = BX_KEY_KP_LEFT; break;
-
- case XK_KP_5:
-#ifdef XK_KP_Begin
- case XK_KP_Begin:
-#endif
- key_event = BX_KEY_KP_5; break;
-
- case XK_KP_6:
-#ifdef XK_KP_Right
- case XK_KP_Right:
-#endif
- key_event = BX_KEY_KP_RIGHT; break;
-
- case XK_KP_7:
-#ifdef XK_KP_Home
- case XK_KP_Home:
-#endif
- key_event = BX_KEY_KP_HOME; break;
-
- case XK_KP_8:
-#ifdef XK_KP_Up
- case XK_KP_Up:
-#endif
- key_event = BX_KEY_KP_UP; break;
-
- case XK_KP_9:
-#ifdef XK_KP_Page_Up
- case XK_KP_Page_Up:
-#endif
- key_event = BX_KEY_KP_PAGE_UP; break;
-
- case XK_KP_0:
-#ifdef XK_KP_Insert
- case XK_KP_Insert:
-#endif
- key_event = BX_KEY_KP_INSERT; break;
-
- case XK_KP_Decimal:
-#ifdef XK_KP_Delete
- case XK_KP_Delete:
-#endif
- key_event = BX_KEY_KP_DELETE; break;
-
-#ifdef XK_KP_Enter
- case XK_KP_Enter: key_event = BX_KEY_KP_ENTER; break;
-#endif
-
- case XK_KP_Subtract: key_event = BX_KEY_KP_SUBTRACT; break;
- case XK_KP_Add: key_event = BX_KEY_KP_ADD; break;
-
- case XK_KP_Multiply: key_event = BX_KEY_KP_MULTIPLY; break;
- case XK_KP_Divide: key_event = BX_KEY_KP_DIVIDE; break;
-
-
- case XK_Up: key_event = BX_KEY_UP; break;
- case XK_Down: key_event = BX_KEY_DOWN; break;
- case XK_Left: key_event = BX_KEY_LEFT; break;
- case XK_Right: key_event = BX_KEY_RIGHT; break;
-
-
- case XK_Delete: key_event = BX_KEY_DELETE; break;
- case XK_BackSpace: key_event = BX_KEY_BACKSPACE; break;
- case XK_Tab: key_event = BX_KEY_TAB; break;
-#ifdef XK_ISO_Left_Tab
- case XK_ISO_Left_Tab: key_event = BX_KEY_TAB; break;
-#endif
- case XK_Return: key_event = BX_KEY_ENTER; break;
- case XK_Escape: key_event = BX_KEY_ESC; break;
- case XK_F1: key_event = BX_KEY_F1; break;
- case XK_F2: key_event = BX_KEY_F2; break;
- case XK_F3: key_event = BX_KEY_F3; break;
- case XK_F4: key_event = BX_KEY_F4; break;
- case XK_F5: key_event = BX_KEY_F5; break;
- case XK_F6: key_event = BX_KEY_F6; break;
- case XK_F7: key_event = BX_KEY_F7; break;
- case XK_F8: key_event = BX_KEY_F8; break;
- case XK_F9: key_event = BX_KEY_F9; break;
- case XK_F10: key_event = BX_KEY_F10; break;
- case XK_F11: key_event = BX_KEY_F11; break;
- case XK_F12: key_event = BX_KEY_F12; break;
- case XK_Control_L: key_event = BX_KEY_CTRL_L; break;
-#ifdef XK_Control_R
- case XK_Control_R: key_event = BX_KEY_CTRL_R; break;
-#endif
- case XK_Shift_L: key_event = BX_KEY_SHIFT_L; break;
- case XK_Shift_R: key_event = BX_KEY_SHIFT_R; break;
- case XK_Alt_L: key_event = BX_KEY_ALT_L; break;
-#ifdef XK_Alt_R
- case XK_Alt_R: key_event = BX_KEY_ALT_R; break;
-#endif
- case XK_Caps_Lock: key_event = BX_KEY_CAPS_LOCK; break;
- case XK_Num_Lock: key_event = BX_KEY_NUM_LOCK; break;
-#ifdef XK_Scroll_Lock
- case XK_Scroll_Lock: key_event = BX_KEY_SCRL_LOCK; break;
-#endif
-#ifdef XK_Print
- case XK_Print: key_event = BX_KEY_PRINT; break;
-#endif
-#ifdef XK_Pause
- case XK_Pause: key_event = BX_KEY_PAUSE; break;
-#endif
-
- case XK_Insert: key_event = BX_KEY_INSERT; break;
- case XK_Home: key_event = BX_KEY_HOME; break;
- case XK_End: key_event = BX_KEY_END; break;
- case XK_Page_Up: key_event = BX_KEY_PAGE_UP; break;
- case XK_Page_Down: key_event = BX_KEY_PAGE_DOWN; break;
-
- default:
- BX_ERROR(("rfbKeyPress(): key %04x unhandled!", key));
- fprintf(stderr, "RFB: rfbKeyPress(): key %04x unhandled!\n", key);
- return;
- break;
- }
- }
-
- if (press_release) key_event |= BX_KEY_RELEASED;
- DEV_kbd_gen_scancode(key_event);
-}
-
-void rfbMouseMove(int x, int y, int bmask)
-{
- static int oldx = -1;
- static int oldy = -1;
- int xorigin;
-
- if (oldx == oldy == -1) {
- oldx = x;
- oldy = y;
- return;
- }
- if(y > rfbHeaderbarY) {
- //DEV_mouse_motion(x, y - rfbHeaderbarY, buttons);
- DEV_mouse_motion(x - oldx, oldy - y, bmask);
- oldx = x;
- oldy = y;
- } else {
- if (bmask == 1) {
- for (unsigned i=0; i<rfbHeaderbarBitmapCount; i++) {
- if (rfbHeaderbarBitmaps[i].alignment == BX_GRAVITY_LEFT)
- xorigin = rfbHeaderbarBitmaps[i].xorigin;
- else
- xorigin = rfbDimensionX - rfbHeaderbarBitmaps[i].xorigin;
- if ( (x>=xorigin) && (x<(xorigin+int(rfbBitmaps[rfbHeaderbarBitmaps[i].index].xdim))) ) {
- rfbHeaderbarBitmaps[i].f();
- return;
- }
- }
- }
- }
-}
-
- void
-bx_rfb_gui_c::mouse_enabled_changed_specific (bx_bool val)
-{
-}
-
-#endif /* if BX_WITH_RFB */
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: rfb.h,v 1.2 2001/10/03 13:10:37 bdenney Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// rfb.h
-// This includes the rfb spec header, the port numbers,
-// the CARD type definitions and various useful macros.
-//
-
-#ifndef RFB_H__
-#define RFB_H__
-
-// Define the CARD* types as used in X11/Xmd.h
-
-typedef unsigned long CARD32;
-typedef unsigned short CARD16;
-typedef short INT16;
-typedef unsigned char CARD8;
-
-// Define the port number offsets
-#define FLASH_PORT_OFFSET 5400
-#define INCOMING_PORT_OFFSET 5500
-#define HTTP_PORT_OFFSET 5800 // we don't use this in Venice
-#define RFB_PORT_OFFSET 5900
-
-#define _SIZEOF(x) sz_##x
-#define SIZEOF(x) _SIZEOF(x)
-
-#define PORT_TO_DISPLAY(p) ( (p) - RFB_PORT_OFFSET )
-#define DISPLAY_TO_PORT(d) ( (d) + RFB_PORT_OFFSET )
-
-#define EWOULDBLOCK WSAEWOULDBLOCK
-#define ETIMEDOUT WSAETIMEDOUT
-
-#endif
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: rfbproto.h,v 1.2 2001/10/03 13:10:37 bdenney Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-/*
- * Copyright (C) 1997, 1998 Olivetti & Oracle Research Laboratory
- *
- * This is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This software is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this software; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
- * USA.
- */
-
-/*
- * rfbproto.h - header file for the RFB protocol version 3.3
- *
- * Uses types CARD<n> for an n-bit unsigned integer, INT<n> for an n-bit signed
- * integer (for n = 8, 16 and 32).
- *
- * All multiple byte integers are in big endian (network) order (most
- * significant byte first). Unless noted otherwise there is no special
- * alignment of protocol structures.
- *
- *
- * Once the initial handshaking is done, all messages start with a type byte,
- * (usually) followed by message-specific data. The order of definitions in
- * this file is as follows:
- *
- * (1) Structures used in several types of message.
- * (2) Structures used in the initial handshaking.
- * (3) Message types.
- * (4) Encoding types.
- * (5) For each message type, the form of the data following the type byte.
- * Sometimes this is defined by a single structure but the more complex
- * messages have to be explained by comments.
- */
-
-
-/*****************************************************************************
- *
- * Structures used in several messages
- *
- *****************************************************************************/
-
-/*-----------------------------------------------------------------------------
- * Structure used to specify a rectangle. This structure is a multiple of 4
- * bytes so that it can be interspersed with 32-bit pixel data without
- * affecting alignment.
- */
-
-typedef struct {
- CARD16 x;
- CARD16 y;
- CARD16 w;
- CARD16 h;
-} rfbRectangle;
-
-#define sz_rfbRectangle 8
-
-
-/*-----------------------------------------------------------------------------
- * Structure used to specify pixel format.
- */
-
-typedef struct {
-
- CARD8 bitsPerPixel; /* 8,16,32 only */
-
- CARD8 depth; /* 8 to 32 */
-
- CARD8 bigEndian; /* True if multi-byte pixels are interpreted
- as big endian, or if single-bit-per-pixel
- has most significant bit of the byte
- corresponding to first (leftmost) pixel. Of
- course this is meaningless for 8 bits/pix */
-
- CARD8 trueColour; /* If false then we need a "colour map" to
- convert pixels to RGB. If true, xxxMax and
- xxxShift specify bits used for red, green
- and blue */
-
- /* the following fields are only meaningful if trueColour is true */
-
- CARD16 redMax; /* maximum red value (= 2^n - 1 where n is the
- number of bits used for red). Note this
- value is always in big endian order. */
-
- CARD16 greenMax; /* similar for green */
-
- CARD16 blueMax; /* and blue */
-
- CARD8 redShift; /* number of shifts needed to get the red
- value in a pixel to the least significant
- bit. To find the red value from a given
- pixel, do the following:
- 1) Swap pixel value according to bigEndian
- (e.g. if bigEndian is false and host byte
- order is big endian, then swap).
- 2) Shift right by redShift.
- 3) AND with redMax (in host byte order).
- 4) You now have the red value between 0 and
- redMax. */
-
- CARD8 greenShift; /* similar for green */
-
- CARD8 blueShift; /* and blue */
-
- CARD8 pad1;
- CARD16 pad2;
-
-} rfbPixelFormat;
-
-#define sz_rfbPixelFormat 16
-
-
-
-/*****************************************************************************
- *
- * Initial handshaking messages
- *
- *****************************************************************************/
-
-/*-----------------------------------------------------------------------------
- * Protocol Version
- *
- * The server always sends 12 bytes to start which identifies the latest RFB
- * protocol version number which it supports. These bytes are interpreted
- * as a string of 12 ASCII characters in the format "RFB xxx.yyy\n" where
- * xxx and yyy are the major and minor version numbers (for version 3.3
- * this is "RFB 003.003\n").
- *
- * The client then replies with a similar 12-byte message giving the version
- * number of the protocol which should actually be used (which may be different
- * to that quoted by the server).
- *
- * It is intended that both clients and servers may provide some level of
- * backwards compatibility by this mechanism. Servers in particular should
- * attempt to provide backwards compatibility, and even forwards compatibility
- * to some extent. For example if a client demands version 3.1 of the
- * protocol, a 3.0 server can probably assume that by ignoring requests for
- * encoding types it doesn't understand, everything will still work OK. This
- * will probably not be the case for changes in the major version number.
- *
- * The format string below can be used in sprintf or sscanf to generate or
- * decode the version string respectively.
- */
-
-#define rfbProtocolVersionFormat "RFB %03d.%03d\n"
-#define rfbProtocolMajorVersion 3
-#define rfbProtocolMinorVersion 3
-
-typedef char rfbProtocolVersionMsg[13]; /* allow extra byte for null */
-
-#define sz_rfbProtocolVersionMsg 12
-
-
-/*-----------------------------------------------------------------------------
- * Authentication
- *
- * Once the protocol version has been decided, the server then sends a 32-bit
- * word indicating whether any authentication is needed on the connection.
- * The value of this word determines the authentication scheme in use. For
- * version 3.0 of the protocol this may have one of the following values:
- */
-
-#define rfbConnFailed 0
-#define rfbNoAuth 1
-#define rfbVncAuth 2
-
-/*
- * rfbConnFailed: For some reason the connection failed (e.g. the server
- * cannot support the desired protocol version). This is
- * followed by a string describing the reason (where a
- * string is specified as a 32-bit length followed by that
- * many ASCII characters).
- *
- * rfbNoAuth: No authentication is needed.
- *
- * rfbVncAuth: The VNC authentication scheme is to be used. A 16-byte
- * challenge follows, which the client encrypts as
- * appropriate using the password and sends the resulting
- * 16-byte response. If the response is correct, the
- * server sends the 32-bit word rfbVncAuthOK. If a simple
- * failure happens, the server sends rfbVncAuthFailed and
- * closes the connection. If the server decides that too
- * many failures have occurred, it sends rfbVncAuthTooMany
- * and closes the connection. In the latter case, the
- * server should not allow an immediate reconnection by
- * the client.
- */
-
-#define rfbVncAuthOK 0
-#define rfbVncAuthFailed 1
-#define rfbVncAuthTooMany 2
-
-
-/*-----------------------------------------------------------------------------
- * Client Initialisation Message
- *
- * Once the client and server are sure that they're happy to talk to one
- * another, the client sends an initialisation message. At present this
- * message only consists of a boolean indicating whether the server should try
- * to share the desktop by leaving other clients connected, or give exclusive
- * access to this client by disconnecting all other clients.
- */
-
-typedef struct {
- CARD8 shared;
-} rfbClientInitMsg;
-
-#define sz_rfbClientInitMsg 1
-
-
-/*-----------------------------------------------------------------------------
- * Server Initialisation Message
- *
- * After the client initialisation message, the server sends one of its own.
- * This tells the client the width and height of the server's framebuffer,
- * its pixel format and the name associated with the desktop.
- */
-
-typedef struct {
- CARD16 framebufferWidth;
- CARD16 framebufferHeight;
- rfbPixelFormat format; /* the server's preferred pixel format */
- CARD32 nameLength;
- /* followed by char name[nameLength] */
-} rfbServerInitMsg;
-
-#define sz_rfbServerInitMsg (8 + sz_rfbPixelFormat)
-
-
-/*
- * Following the server initialisation message it's up to the client to send
- * whichever protocol messages it wants. Typically it will send a
- * SetPixelFormat message and a SetEncodings message, followed by a
- * FramebufferUpdateRequest. From then on the server will send
- * FramebufferUpdate messages in response to the client's
- * FramebufferUpdateRequest messages. The client should send
- * FramebufferUpdateRequest messages with incremental set to true when it has
- * finished processing one FramebufferUpdate and is ready to process another.
- * With a fast client, the rate at which FramebufferUpdateRequests are sent
- * should be regulated to avoid hogging the network.
- */
-
-
-
-/*****************************************************************************
- *
- * Message types
- *
- *****************************************************************************/
-
-/* server -> client */
-
-#define rfbFramebufferUpdate 0
-#define rfbSetColourMapEntries 1
-#define rfbBell 2
-#define rfbServerCutText 3
-
-
-/* client -> server */
-
-#define rfbSetPixelFormat 0
-#define rfbFixColourMapEntries 1 /* not currently supported */
-#define rfbSetEncodings 2
-#define rfbFramebufferUpdateRequest 3
-#define rfbKeyEvent 4
-#define rfbPointerEvent 5
-#define rfbClientCutText 6
-
-
-
-
-/*****************************************************************************
- *
- * Encoding types
- *
- *****************************************************************************/
-
-#define rfbEncodingRaw 0
-#define rfbEncodingCopyRect 1
-#define rfbEncodingRRE 2
-#define rfbEncodingCoRRE 4
-#define rfbEncodingHextile 5
-
-
-
-/*****************************************************************************
- *
- * Server -> client message definitions
- *
- *****************************************************************************/
-
-
-/*-----------------------------------------------------------------------------
- * FramebufferUpdate - a block of rectangles to be copied to the framebuffer.
- *
- * This message consists of a header giving the number of rectangles of pixel
- * data followed by the rectangles themselves. The header is padded so that
- * together with the type byte it is an exact multiple of 4 bytes (to help
- * with alignment of 32-bit pixels):
- */
-
-typedef struct {
- CARD8 type; /* always rfbFramebufferUpdate */
- CARD8 pad;
- CARD16 nRects;
- /* followed by nRects rectangles */
-} rfbFramebufferUpdateMsg;
-
-#define sz_rfbFramebufferUpdateMsg 4
-
-/*
- * Each rectangle of pixel data consists of a header describing the position
- * and size of the rectangle and a type word describing the encoding of the
- * pixel data, followed finally by the pixel data. Note that if the client has
- * not sent a SetEncodings message then it will only receive raw pixel data.
- * Also note again that this structure is a multiple of 4 bytes.
- */
-
-typedef struct {
- rfbRectangle r;
- CARD32 encoding; /* one of the encoding types rfbEncoding... */
-} rfbFramebufferUpdateRectHeader;
-
-#define sz_rfbFramebufferUpdateRectHeader (sz_rfbRectangle + 4)
-
-
-/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- * Raw Encoding. Pixels are sent in top-to-bottom scanline order,
- * left-to-right within a scanline with no padding in between.
- */
-
-
-/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- * CopyRect Encoding. The pixels are specified simply by the x and y position
- * of the source rectangle.
- */
-
-typedef struct {
- CARD16 srcX;
- CARD16 srcY;
-} rfbCopyRect;
-
-#define sz_rfbCopyRect 4
-
-
-/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- * RRE - Rise-and-Run-length Encoding. We have an rfbRREHeader structure
- * giving the number of subrectangles following. Finally the data follows in
- * the form [<bgpixel><subrect><subrect>...] where each <subrect> is
- * [<pixel><rfbRectangle>].
- */
-
-typedef struct {
- CARD32 nSubrects;
-} rfbRREHeader;
-
-#define sz_rfbRREHeader 4
-
-
-/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- * CoRRE - Compact RRE Encoding. We have an rfbRREHeader structure giving
- * the number of subrectangles following. Finally the data follows in the form
- * [<bgpixel><subrect><subrect>...] where each <subrect> is
- * [<pixel><rfbCoRRERectangle>]. This means that
- * the whole rectangle must be at most 255x255 pixels.
- */
-
-typedef struct {
- CARD8 x;
- CARD8 y;
- CARD8 w;
- CARD8 h;
-} rfbCoRRERectangle;
-
-#define sz_rfbCoRRERectangle 4
-
-
-/*- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- * Hextile Encoding. The rectangle is divided up into "tiles" of 16x16 pixels,
- * starting at the top left going in left-to-right, top-to-bottom order. If
- * the width of the rectangle is not an exact multiple of 16 then the width of
- * the last tile in each row will be correspondingly smaller. Similarly if the
- * height is not an exact multiple of 16 then the height of each tile in the
- * final row will also be smaller. Each tile begins with a "subencoding" type
- * byte, which is a mask made up of a number of bits. If the Raw bit is set
- * then the other bits are irrelevant; w*h pixel values follow (where w and h
- * are the width and height of the tile). Otherwise the tile is encoded in a
- * similar way to RRE, except that the position and size of each subrectangle
- * can be specified in just two bytes. The other bits in the mask are as
- * follows:
- *
- * BackgroundSpecified - if set, a pixel value follows which specifies
- * the background colour for this tile. The first non-raw tile in a
- * rectangle must have this bit set. If this bit isn't set then the
- * background is the same as the last tile.
- *
- * ForegroundSpecified - if set, a pixel value follows which specifies
- * the foreground colour to be used for all subrectangles in this tile.
- * If this bit is set then the SubrectsColoured bit must be zero.
- *
- * AnySubrects - if set, a single byte follows giving the number of
- * subrectangles following. If not set, there are no subrectangles (i.e.
- * the whole tile is just solid background colour).
- *
- * SubrectsColoured - if set then each subrectangle is preceded by a pixel
- * value giving the colour of that subrectangle. If not set, all
- * subrectangles are the same colour, the foreground colour; if the
- * ForegroundSpecified bit wasn't set then the foreground is the same as
- * the last tile.
- *
- * The position and size of each subrectangle is specified in two bytes. The
- * Pack macros below can be used to generate the two bytes from x, y, w, h,
- * and the Extract macros can be used to extract the x, y, w, h values from
- * the two bytes.
- */
-
-#define rfbHextileRaw (1 << 0)
-#define rfbHextileBackgroundSpecified (1 << 1)
-#define rfbHextileForegroundSpecified (1 << 2)
-#define rfbHextileAnySubrects (1 << 3)
-#define rfbHextileSubrectsColoured (1 << 4)
-
-#define rfbHextilePackXY(x,y) (((x) << 4) | (y))
-#define rfbHextilePackWH(w,h) ((((w)-1) << 4) | ((h)-1))
-#define rfbHextileExtractX(byte) ((byte) >> 4)
-#define rfbHextileExtractY(byte) ((byte) & 0xf)
-#define rfbHextileExtractW(byte) (((byte) >> 4) + 1)
-#define rfbHextileExtractH(byte) (((byte) & 0xf) + 1)
-
-
-/*-----------------------------------------------------------------------------
- * SetColourMapEntries - these messages are only sent if the pixel
- * format uses a "colour map" (i.e. trueColour false) and the client has not
- * fixed the entire colour map using FixColourMapEntries. In addition they
- * will only start being sent after the client has sent its first
- * FramebufferUpdateRequest. So if the client always tells the server to use
- * trueColour then it never needs to process this type of message.
- */
-
-typedef struct {
- CARD8 type; /* always rfbSetColourMapEntries */
- CARD8 pad;
- CARD16 firstColour;
- CARD16 nColours;
-
- /* Followed by nColours * 3 * CARD16
- r1, g1, b1, r2, g2, b2, r3, g3, b3, ..., rn, bn, gn */
-
-} rfbSetColourMapEntriesMsg;
-
-#define sz_rfbSetColourMapEntriesMsg 6
-
-
-
-/*-----------------------------------------------------------------------------
- * Bell - ring a bell on the client if it has one.
- */
-
-typedef struct {
- CARD8 type; /* always rfbBell */
-} rfbBellMsg;
-
-#define sz_rfbBellMsg 1
-
-
-
-/*-----------------------------------------------------------------------------
- * ServerCutText - the server has new text in its cut buffer.
- */
-
-typedef struct {
- CARD8 type; /* always rfbServerCutText */
- CARD8 pad1;
- CARD16 pad2;
- CARD32 length;
- /* followed by char text[length] */
-} rfbServerCutTextMsg;
-
-#define sz_rfbServerCutTextMsg 8
-
-
-/*-----------------------------------------------------------------------------
- * Union of all server->client messages.
- */
-
-typedef union {
- CARD8 type;
- rfbFramebufferUpdateMsg fu;
- rfbSetColourMapEntriesMsg scme;
- rfbBellMsg b;
- rfbServerCutTextMsg sct;
-} rfbServerToClientMsg;
-
-
-
-/*****************************************************************************
- *
- * Message definitions (client -> server)
- *
- *****************************************************************************/
-
-
-/*-----------------------------------------------------------------------------
- * SetPixelFormat - tell the RFB server the format in which the client wants
- * pixels sent.
- */
-
-typedef struct {
- CARD8 type; /* always rfbSetPixelFormat */
- CARD8 pad1;
- CARD16 pad2;
- rfbPixelFormat format;
-} rfbSetPixelFormatMsg;
-
-#define sz_rfbSetPixelFormatMsg (sz_rfbPixelFormat + 4)
-
-
-/*-----------------------------------------------------------------------------
- * FixColourMapEntries - when the pixel format uses a "colour map", fix
- * read-only colour map entries.
- *
- * ***************** NOT CURRENTLY SUPPORTED *****************
- */
-
-typedef struct {
- CARD8 type; /* always rfbFixColourMapEntries */
- CARD8 pad;
- CARD16 firstColour;
- CARD16 nColours;
-
- /* Followed by nColours * 3 * CARD16
- r1, g1, b1, r2, g2, b2, r3, g3, b3, ..., rn, bn, gn */
-
-} rfbFixColourMapEntriesMsg;
-
-#define sz_rfbFixColourMapEntriesMsg 6
-
-
-/*-----------------------------------------------------------------------------
- * SetEncodings - tell the RFB server which encoding types we accept. Put them
- * in order of preference, if we have any. We may always receive raw
- * encoding, even if we don't specify it here.
- */
-
-typedef struct {
- CARD8 type; /* always rfbSetEncodings */
- CARD8 pad;
- CARD16 nEncodings;
- /* followed by nEncodings * CARD32 encoding types */
-} rfbSetEncodingsMsg;
-
-#define sz_rfbSetEncodingsMsg 4
-
-
-/*-----------------------------------------------------------------------------
- * FramebufferUpdateRequest - request for a framebuffer update. If incremental
- * is true then the client just wants the changes since the last update. If
- * false then it wants the whole of the specified rectangle.
- */
-
-typedef struct {
- CARD8 type; /* always rfbFramebufferUpdateRequest */
- CARD8 incremental;
- CARD16 x;
- CARD16 y;
- CARD16 w;
- CARD16 h;
-} rfbFramebufferUpdateRequestMsg;
-
-#define sz_rfbFramebufferUpdateRequestMsg 10
-
-
-/*-----------------------------------------------------------------------------
- * KeyEvent - key press or release
- *
- * Keys are specified using the "keysym" values defined by the X Window System.
- * For most ordinary keys, the keysym is the same as the corresponding ASCII
- * value. Other common keys are:
- *
- * BackSpace 0xff08
- * Tab 0xff09
- * Return or Enter 0xff0d
- * Escape 0xff1b
- * Insert 0xff63
- * Delete 0xffff
- * Home 0xff50
- * End 0xff57
- * Page Up 0xff55
- * Page Down 0xff56
- * Left 0xff51
- * Up 0xff52
- * Right 0xff53
- * Down 0xff54
- * F1 0xffbe
- * F2 0xffbf
- * ... ...
- * F12 0xffc9
- * Shift 0xffe1
- * Control 0xffe3
- * Meta 0xffe7
- * Alt 0xffe9
- */
-
-typedef struct {
- CARD8 type; /* always rfbKeyEvent */
- CARD8 down; /* true if down (press), false if up */
- CARD16 pad;
- CARD32 key; /* key is specified as an X keysym */
-} rfbKeyEventMsg;
-
-#define sz_rfbKeyEventMsg 8
-
-
-/*-----------------------------------------------------------------------------
- * PointerEvent - mouse/pen move and/or button press.
- */
-
-typedef struct {
- CARD8 type; /* always rfbPointerEvent */
- CARD8 buttonMask; /* bits 0-7 are buttons 1-8, 0=up, 1=down */
- CARD16 x;
- CARD16 y;
-} rfbPointerEventMsg;
-
-#define rfbButton1Mask 1
-#define rfbButton2Mask 2
-#define rfbButton3Mask 4
-
-#define sz_rfbPointerEventMsg 6
-
-
-
-/*-----------------------------------------------------------------------------
- * ClientCutText - the client has new text in its cut buffer.
- */
-
-typedef struct {
- CARD8 type; /* always rfbClientCutText */
- CARD8 pad1;
- CARD16 pad2;
- CARD32 length;
- /* followed by char text[length] */
-} rfbClientCutTextMsg;
-
-#define sz_rfbClientCutTextMsg 8
-
-
-
-/*-----------------------------------------------------------------------------
- * Union of all client->server messages.
- */
-
-typedef union {
- CARD8 type;
- rfbSetPixelFormatMsg spf;
- rfbFixColourMapEntriesMsg fcme;
- rfbSetEncodingsMsg se;
- rfbFramebufferUpdateRequestMsg fur;
- rfbKeyEventMsg ke;
- rfbPointerEventMsg pe;
- rfbClientCutTextMsg cct;
-} rfbClientToServerMsg;
+++ /dev/null
-#define BX_HEADERBAR_FG_RED 0x10
-#define BX_HEADERBAR_FG_GREEN 0x10
-#define BX_HEADERBAR_FG_BLUE 0x10
-#define BX_HEADERBAR_BG_RED 0xD0
-#define BX_HEADERBAR_BG_GREEN 0xD0
-#define BX_HEADERBAR_BG_BLUE 0xD0
-
-unsigned char sdl_font8x16[256][16] = {
- { 0, 0, 0, 0, 0, 0, 0, 0, // 0
- 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 126, 129, 165, 129, 129, 189, // 1
- 153, 129, 129, 126, 0, 0, 0, 0 },
- { 0, 0, 126, 255, 219, 255, 255, 195, // 2
- 231, 255, 255, 126, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 108, 254, 254, 254, // 3
- 254, 124, 56, 16, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 16, 56, 124, 254, // 4
- 124, 56, 16, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 24, 60, 60, 231, 231, // 5
- 231, 24, 24, 60, 0, 0, 0, 0 },
- { 0, 0, 0, 24, 60, 126, 255, 255, // 6
- 126, 24, 24, 60, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 24, 60, // 7
- 60, 24, 0, 0, 0, 0, 0, 0 },
- { 255, 255, 255, 255, 255, 255, 231, 195, // 8
- 195, 231, 255, 255, 255, 255, 255, 255 },
- { 0, 0, 0, 0, 0, 60, 102, 66, // 9
- 66, 102, 60, 0, 0, 0, 0, 0 },
- { 255, 255, 255, 255, 255, 195, 153, 189, // 10
- 189, 153, 195, 255, 255, 255, 255, 255 },
- { 0, 0, 30, 14, 26, 50, 120, 204, // 11
- 204, 204, 204, 120, 0, 0, 0, 0 },
- { 0, 0, 60, 102, 102, 102, 102, 60, // 12
- 24, 126, 24, 24, 0, 0, 0, 0 },
- { 0, 0, 63, 51, 63, 48, 48, 48, // 13
- 48, 112, 240, 224, 0, 0, 0, 0 },
- { 0, 0, 127, 99, 127, 99, 99, 99, // 14
- 99, 103, 231, 230, 192, 0, 0, 0 },
- { 0, 0, 0, 24, 24, 219, 60, 231, // 15
- 60, 219, 24, 24, 0, 0, 0, 0 },
- { 0, 128, 192, 224, 240, 248, 254, 248, // 16
- 240, 224, 192, 128, 0, 0, 0, 0 },
- { 0, 2, 6, 14, 30, 62, 254, 62, // 17
- 30, 14, 6, 2, 0, 0, 0, 0 },
- { 0, 0, 24, 60, 126, 24, 24, 24, // 18
- 126, 60, 24, 0, 0, 0, 0, 0 },
- { 0, 0, 102, 102, 102, 102, 102, 102, // 19
- 102, 0, 102, 102, 0, 0, 0, 0 },
- { 0, 0, 127, 219, 219, 219, 123, 27, // 20
- 27, 27, 27, 27, 0, 0, 0, 0 },
- { 0, 124, 198, 96, 56, 108, 198, 198, // 21
- 108, 56, 12, 198, 124, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, // 22
- 254, 254, 254, 254, 0, 0, 0, 0 },
- { 0, 0, 24, 60, 126, 24, 24, 24, // 23
- 126, 60, 24, 126, 0, 0, 0, 0 },
- { 0, 0, 24, 60, 126, 24, 24, 24, // 24
- 24, 24, 24, 24, 0, 0, 0, 0 },
- { 0, 0, 24, 24, 24, 24, 24, 24, // 25
- 24, 126, 60, 24, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 24, 12, 254, // 26
- 12, 24, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 48, 96, 254, // 27
- 96, 48, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 192, 192, // 28
- 192, 254, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 40, 108, 254, // 29
- 108, 40, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 16, 56, 56, 124, // 30
- 124, 254, 254, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 254, 254, 124, 124, // 31
- 56, 56, 16, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, // 32
- 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 24, 60, 60, 60, 24, 24, // 33
- 24, 0, 24, 24, 0, 0, 0, 0 },
- { 0, 102, 102, 102, 36, 0, 0, 0, // 34
- 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 108, 108, 254, 108, 108, // 35
- 108, 254, 108, 108, 0, 0, 0, 0 },
- { 24, 24, 124, 198, 194, 192, 124, 6, // 36
- 6, 134, 198, 124, 24, 24, 0, 0 },
- { 0, 0, 0, 0, 194, 198, 12, 24, // 37
- 48, 96, 198, 134, 0, 0, 0, 0 },
- { 0, 0, 56, 108, 108, 56, 118, 220, // 38
- 204, 204, 204, 118, 0, 0, 0, 0 },
- { 0, 48, 48, 48, 96, 0, 0, 0, // 39
- 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 12, 24, 48, 48, 48, 48, // 40
- 48, 48, 24, 12, 0, 0, 0, 0 },
- { 0, 0, 48, 24, 12, 12, 12, 12, // 41
- 12, 12, 24, 48, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 102, 60, 255, // 42
- 60, 102, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 24, 24, 126, // 43
- 24, 24, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, // 44
- 0, 24, 24, 24, 48, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 254, // 45
- 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, // 46
- 0, 0, 24, 24, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 2, 6, 12, 24, // 47
- 48, 96, 192, 128, 0, 0, 0, 0 },
- { 0, 0, 56, 108, 198, 198, 214, 214, // 48
- 198, 198, 108, 56, 0, 0, 0, 0 },
- { 0, 0, 24, 56, 120, 24, 24, 24, // 49
- 24, 24, 24, 126, 0, 0, 0, 0 },
- { 0, 0, 124, 198, 6, 12, 24, 48, // 50
- 96, 192, 198, 254, 0, 0, 0, 0 },
- { 0, 0, 124, 198, 6, 6, 60, 6, // 51
- 6, 6, 198, 124, 0, 0, 0, 0 },
- { 0, 0, 12, 28, 60, 108, 204, 254, // 52
- 12, 12, 12, 30, 0, 0, 0, 0 },
- { 0, 0, 254, 192, 192, 192, 252, 6, // 53
- 6, 6, 198, 124, 0, 0, 0, 0 },
- { 0, 0, 56, 96, 192, 192, 252, 198, // 54
- 198, 198, 198, 124, 0, 0, 0, 0 },
- { 0, 0, 254, 198, 6, 6, 12, 24, // 55
- 48, 48, 48, 48, 0, 0, 0, 0 },
- { 0, 0, 124, 198, 198, 198, 124, 198, // 56
- 198, 198, 198, 124, 0, 0, 0, 0 },
- { 0, 0, 124, 198, 198, 198, 126, 6, // 57
- 6, 6, 12, 120, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 24, 24, 0, 0, // 58
- 0, 24, 24, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 24, 24, 0, 0, // 59
- 0, 24, 24, 48, 0, 0, 0, 0 },
- { 0, 0, 0, 6, 12, 24, 48, 96, // 60
- 48, 24, 12, 6, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 126, 0, 0, // 61
- 126, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 96, 48, 24, 12, 6, // 62
- 12, 24, 48, 96, 0, 0, 0, 0 },
- { 0, 0, 124, 198, 198, 12, 24, 24, // 63
- 24, 0, 24, 24, 0, 0, 0, 0 },
- { 0, 0, 0, 124, 198, 198, 222, 222, // 64
- 222, 220, 192, 124, 0, 0, 0, 0 },
- { 0, 0, 16, 56, 108, 198, 198, 254, // 65
- 198, 198, 198, 198, 0, 0, 0, 0 },
- { 0, 0, 252, 102, 102, 102, 124, 102, // 66
- 102, 102, 102, 252, 0, 0, 0, 0 },
- { 0, 0, 60, 102, 194, 192, 192, 192, // 67
- 192, 194, 102, 60, 0, 0, 0, 0 },
- { 0, 0, 248, 108, 102, 102, 102, 102, // 68
- 102, 102, 108, 248, 0, 0, 0, 0 },
- { 0, 0, 254, 102, 98, 104, 120, 104, // 69
- 96, 98, 102, 254, 0, 0, 0, 0 },
- { 0, 0, 254, 102, 98, 104, 120, 104, // 70
- 96, 96, 96, 240, 0, 0, 0, 0 },
- { 0, 0, 60, 102, 194, 192, 192, 222, // 71
- 198, 198, 102, 58, 0, 0, 0, 0 },
- { 0, 0, 198, 198, 198, 198, 254, 198, // 72
- 198, 198, 198, 198, 0, 0, 0, 0 },
- { 0, 0, 60, 24, 24, 24, 24, 24, // 73
- 24, 24, 24, 60, 0, 0, 0, 0 },
- { 0, 0, 30, 12, 12, 12, 12, 12, // 74
- 204, 204, 204, 120, 0, 0, 0, 0 },
- { 0, 0, 230, 102, 102, 108, 120, 120, // 75
- 108, 102, 102, 230, 0, 0, 0, 0 },
- { 0, 0, 240, 96, 96, 96, 96, 96, // 76
- 96, 98, 102, 254, 0, 0, 0, 0 },
- { 0, 0, 198, 238, 254, 254, 214, 198, // 77
- 198, 198, 198, 198, 0, 0, 0, 0 },
- { 0, 0, 198, 230, 246, 254, 222, 206, // 78
- 198, 198, 198, 198, 0, 0, 0, 0 },
- { 0, 0, 124, 198, 198, 198, 198, 198, // 79
- 198, 198, 198, 124, 0, 0, 0, 0 },
- { 0, 0, 252, 102, 102, 102, 124, 96, // 80
- 96, 96, 96, 240, 0, 0, 0, 0 },
- { 0, 0, 124, 198, 198, 198, 198, 198, // 81
- 198, 214, 222, 124, 12, 14, 0, 0 },
- { 0, 0, 252, 102, 102, 102, 124, 108, // 82
- 102, 102, 102, 230, 0, 0, 0, 0 },
- { 0, 0, 124, 198, 198, 96, 56, 12, // 83
- 6, 198, 198, 124, 0, 0, 0, 0 },
- { 0, 0, 126, 126, 90, 24, 24, 24, // 84
- 24, 24, 24, 60, 0, 0, 0, 0 },
- { 0, 0, 198, 198, 198, 198, 198, 198, // 85
- 198, 198, 198, 124, 0, 0, 0, 0 },
- { 0, 0, 198, 198, 198, 198, 198, 198, // 86
- 198, 108, 56, 16, 0, 0, 0, 0 },
- { 0, 0, 198, 198, 198, 198, 214, 214, // 87
- 214, 254, 238, 108, 0, 0, 0, 0 },
- { 0, 0, 198, 198, 108, 124, 56, 56, // 88
- 124, 108, 198, 198, 0, 0, 0, 0 },
- { 0, 0, 102, 102, 102, 102, 60, 24, // 89
- 24, 24, 24, 60, 0, 0, 0, 0 },
- { 0, 0, 254, 198, 134, 12, 24, 48, // 90
- 96, 194, 198, 254, 0, 0, 0, 0 },
- { 0, 0, 60, 48, 48, 48, 48, 48, // 91
- 48, 48, 48, 60, 0, 0, 0, 0 },
- { 0, 0, 0, 128, 192, 224, 112, 56, // 92
- 28, 14, 6, 2, 0, 0, 0, 0 },
- { 0, 0, 60, 12, 12, 12, 12, 12, // 93
- 12, 12, 12, 60, 0, 0, 0, 0 },
- { 16, 56, 108, 198, 0, 0, 0, 0, // 94
- 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, // 95
- 0, 0, 0, 0, 0, 255, 0, 0 },
- { 0, 48, 24, 12, 0, 0, 0, 0, // 96
- 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 120, 12, 124, // 97
- 204, 204, 204, 118, 0, 0, 0, 0 },
- { 0, 0, 224, 96, 96, 120, 108, 102, // 98
- 102, 102, 102, 124, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 124, 198, 192, // 99
- 192, 192, 198, 124, 0, 0, 0, 0 },
- { 0, 0, 28, 12, 12, 60, 108, 204, // 100
- 204, 204, 204, 118, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 124, 198, 254, // 101
- 192, 192, 198, 124, 0, 0, 0, 0 },
- { 0, 0, 28, 54, 50, 48, 120, 48, // 102
- 48, 48, 48, 120, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 118, 204, 204, // 103
- 204, 204, 204, 124, 12, 204, 120, 0 },
- { 0, 0, 224, 96, 96, 108, 118, 102, // 104
- 102, 102, 102, 230, 0, 0, 0, 0 },
- { 0, 0, 24, 24, 0, 56, 24, 24, // 105
- 24, 24, 24, 60, 0, 0, 0, 0 },
- { 0, 0, 6, 6, 0, 14, 6, 6, // 106
- 6, 6, 6, 6, 102, 102, 60, 0 },
- { 0, 0, 224, 96, 96, 102, 108, 120, // 107
- 120, 108, 102, 230, 0, 0, 0, 0 },
- { 0, 0, 56, 24, 24, 24, 24, 24, // 108
- 24, 24, 24, 60, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 236, 254, 214, // 109
- 214, 214, 214, 198, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 220, 102, 102, // 110
- 102, 102, 102, 102, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 124, 198, 198, // 111
- 198, 198, 198, 124, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 220, 102, 102, // 112
- 102, 102, 102, 124, 96, 96, 240, 0 },
- { 0, 0, 0, 0, 0, 118, 204, 204, // 113
- 204, 204, 204, 124, 12, 12, 30, 0 },
- { 0, 0, 0, 0, 0, 220, 118, 102, // 114
- 96, 96, 96, 240, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 124, 198, 96, // 115
- 56, 12, 198, 124, 0, 0, 0, 0 },
- { 0, 0, 16, 48, 48, 252, 48, 48, // 116
- 48, 48, 54, 28, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 204, 204, 204, // 117
- 204, 204, 204, 118, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 198, 198, 198, // 118
- 198, 198, 108, 56, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 198, 198, 214, // 119
- 214, 214, 254, 108, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 198, 108, 56, // 120
- 56, 56, 108, 198, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 198, 198, 198, // 121
- 198, 198, 198, 126, 6, 12, 248, 0 },
- { 0, 0, 0, 0, 0, 254, 204, 24, // 122
- 48, 96, 198, 254, 0, 0, 0, 0 },
- { 0, 0, 14, 24, 24, 24, 112, 24, // 123
- 24, 24, 24, 14, 0, 0, 0, 0 },
- { 0, 0, 24, 24, 24, 24, 24, 24, // 124
- 24, 24, 24, 24, 0, 0, 0, 0 },
- { 0, 0, 112, 24, 24, 24, 14, 24, // 125
- 24, 24, 24, 112, 0, 0, 0, 0 },
- { 0, 118, 220, 0, 0, 0, 0, 0, // 126
- 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 16, 56, 108, 198, // 127
- 198, 198, 254, 0, 0, 0, 0, 0 },
- { 0, 0, 60, 102, 194, 192, 192, 192, // 128
- 192, 194, 102, 60, 24, 112, 0, 0 },
- { 0, 0, 204, 0, 0, 204, 204, 204, // 129
- 204, 204, 204, 118, 0, 0, 0, 0 },
- { 0, 12, 24, 48, 0, 124, 198, 254, // 130
- 192, 192, 198, 124, 0, 0, 0, 0 },
- { 0, 16, 56, 108, 0, 120, 12, 124, // 131
- 204, 204, 204, 118, 0, 0, 0, 0 },
- { 0, 0, 204, 0, 0, 120, 12, 124, // 132
- 204, 204, 204, 118, 0, 0, 0, 0 },
- { 0, 96, 48, 24, 0, 120, 12, 124, // 133
- 204, 204, 204, 118, 0, 0, 0, 0 },
- { 0, 56, 108, 56, 0, 120, 12, 124, // 134
- 204, 204, 204, 118, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 124, 198, 192, // 135
- 192, 192, 198, 124, 24, 112, 0, 0 },
- { 0, 16, 56, 108, 0, 124, 198, 254, // 136
- 192, 192, 198, 124, 0, 0, 0, 0 },
- { 0, 0, 198, 0, 0, 124, 198, 254, // 137
- 192, 192, 198, 124, 0, 0, 0, 0 },
- { 0, 96, 48, 24, 0, 124, 198, 254, // 138
- 192, 192, 198, 124, 0, 0, 0, 0 },
- { 0, 0, 102, 0, 0, 56, 24, 24, // 139
- 24, 24, 24, 60, 0, 0, 0, 0 },
- { 0, 24, 60, 102, 0, 56, 24, 24, // 140
- 24, 24, 24, 60, 0, 0, 0, 0 },
- { 0, 96, 48, 24, 0, 56, 24, 24, // 141
- 24, 24, 24, 60, 0, 0, 0, 0 },
- { 0, 198, 0, 16, 56, 108, 198, 198, // 142
- 254, 198, 198, 198, 0, 0, 0, 0 },
- { 56, 108, 56, 16, 56, 108, 198, 198, // 143
- 254, 198, 198, 198, 0, 0, 0, 0 },
- { 12, 24, 0, 254, 102, 98, 104, 120, // 144
- 104, 98, 102, 254, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 236, 54, 54, // 145
- 126, 216, 216, 110, 0, 0, 0, 0 },
- { 0, 0, 62, 108, 204, 204, 254, 204, // 146
- 204, 204, 204, 206, 0, 0, 0, 0 },
- { 0, 16, 56, 108, 0, 124, 198, 198, // 147
- 198, 198, 198, 124, 0, 0, 0, 0 },
- { 0, 0, 198, 0, 0, 124, 198, 198, // 148
- 198, 198, 198, 124, 0, 0, 0, 0 },
- { 0, 96, 48, 24, 0, 124, 198, 198, // 149
- 198, 198, 198, 124, 0, 0, 0, 0 },
- { 0, 48, 120, 204, 0, 204, 204, 204, // 150
- 204, 204, 204, 118, 0, 0, 0, 0 },
- { 0, 96, 48, 24, 0, 204, 204, 204, // 151
- 204, 204, 204, 118, 0, 0, 0, 0 },
- { 0, 0, 198, 0, 0, 198, 198, 198, // 152
- 198, 198, 198, 126, 6, 12, 120, 0 },
- { 0, 198, 0, 124, 198, 198, 198, 198, // 153
- 198, 198, 198, 124, 0, 0, 0, 0 },
- { 0, 198, 0, 198, 198, 198, 198, 198, // 154
- 198, 198, 198, 124, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 124, 206, 222, // 155
- 246, 230, 198, 124, 0, 0, 0, 0 },
- { 0, 56, 108, 100, 96, 240, 96, 96, // 156
- 96, 96, 230, 252, 0, 0, 0, 0 },
- { 0, 4, 124, 206, 206, 214, 214, 214, // 157
- 214, 230, 230, 124, 64, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 198, 108, 56, // 158
- 56, 108, 198, 0, 0, 0, 0, 0 },
- { 0, 14, 27, 24, 24, 24, 126, 24, // 159
- 24, 24, 216, 112, 0, 0, 0, 0 },
- { 0, 24, 48, 96, 0, 120, 12, 124, // 160
- 204, 204, 204, 118, 0, 0, 0, 0 },
- { 0, 12, 24, 48, 0, 56, 24, 24, // 161
- 24, 24, 24, 60, 0, 0, 0, 0 },
- { 0, 24, 48, 96, 0, 124, 198, 198, // 162
- 198, 198, 198, 124, 0, 0, 0, 0 },
- { 0, 24, 48, 96, 0, 204, 204, 204, // 163
- 204, 204, 204, 118, 0, 0, 0, 0 },
- { 0, 0, 118, 220, 0, 220, 102, 102, // 164
- 102, 102, 102, 102, 0, 0, 0, 0 },
- { 118, 220, 0, 198, 230, 246, 254, 222, // 165
- 206, 198, 198, 198, 0, 0, 0, 0 },
- { 0, 0, 60, 108, 108, 62, 0, 126, // 166
- 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 56, 108, 108, 56, 0, 124, // 167
- 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 48, 48, 0, 48, 48, 96, // 168
- 192, 198, 198, 124, 0, 0, 0, 0 },
- { 0, 0, 124, 130, 178, 170, 178, 170, // 169
- 170, 130, 124, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 254, 6, // 170
- 6, 6, 6, 0, 0, 0, 0, 0 },
- { 0, 96, 224, 98, 102, 108, 24, 48, // 171
- 96, 220, 134, 12, 24, 62, 0, 0 },
- { 0, 96, 224, 98, 102, 108, 24, 48, // 172
- 102, 206, 154, 63, 6, 6, 0, 0 },
- { 0, 0, 24, 24, 0, 24, 24, 24, // 173
- 60, 60, 60, 24, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 54, 108, 216, // 174
- 108, 54, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 216, 108, 54, // 175
- 108, 216, 0, 0, 0, 0, 0, 0 },
- { 17, 68, 17, 68, 17, 68, 17, 68, // 176
- 17, 68, 17, 68, 17, 68, 17, 68 },
- { 85, 170, 85, 170, 85, 170, 85, 170, // 177
- 85, 170, 85, 170, 85, 170, 85, 170 },
- { 221, 119, 221, 119, 221, 119, 221, 119, // 178
- 221, 119, 221, 119, 221, 119, 221, 119 },
- { 24, 24, 24, 24, 24, 24, 24, 24, // 179
- 24, 24, 24, 24, 24, 24, 24, 24 },
- { 24, 24, 24, 24, 24, 24, 24, 248, // 180
- 24, 24, 24, 24, 24, 24, 24, 24 },
- { 96, 192, 16, 56, 108, 198, 198, 254, // 181
- 198, 198, 198, 198, 0, 0, 0, 0 },
- { 124, 198, 16, 56, 108, 198, 198, 254, // 182
- 198, 198, 198, 198, 0, 0, 0, 0 },
- { 12, 6, 16, 56, 108, 198, 198, 254, // 183
- 198, 198, 198, 198, 0, 0, 0, 0 },
- { 0, 0, 124, 130, 154, 162, 162, 162, // 184
- 154, 130, 124, 0, 0, 0, 0, 0 },
- { 54, 54, 54, 54, 54, 246, 6, 246, // 185
- 54, 54, 54, 54, 54, 54, 54, 54 },
- { 54, 54, 54, 54, 54, 54, 54, 54, // 186
- 54, 54, 54, 54, 54, 54, 54, 54 },
- { 0, 0, 0, 0, 0, 254, 6, 246, // 187
- 54, 54, 54, 54, 54, 54, 54, 54 },
- { 54, 54, 54, 54, 54, 246, 6, 254, // 188
- 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 24, 24, 124, 198, 192, 192, // 189
- 198, 124, 24, 24, 0, 0, 0, 0 },
- { 0, 0, 0, 102, 102, 60, 24, 126, // 190
- 24, 126, 24, 24, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 248, // 191
- 24, 24, 24, 24, 24, 24, 24, 24 },
- { 24, 24, 24, 24, 24, 24, 24, 31, // 192
- 0, 0, 0, 0, 0, 0, 0, 0 },
- { 24, 24, 24, 24, 24, 24, 24, 255, // 193
- 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 255, // 194
- 24, 24, 24, 24, 24, 24, 24, 24 },
- { 24, 24, 24, 24, 24, 24, 24, 31, // 195
- 24, 24, 24, 24, 24, 24, 24, 24 },
- { 0, 0, 0, 0, 0, 0, 0, 255, // 196
- 0, 0, 0, 0, 0, 0, 0, 0 },
- { 24, 24, 24, 24, 24, 24, 24, 255, // 197
- 24, 24, 24, 24, 24, 24, 24, 24 },
- { 0, 0, 118, 220, 0, 120, 12, 124, // 198
- 204, 204, 204, 118, 0, 0, 0, 0 },
- { 118, 220, 0, 56, 108, 198, 198, 254, // 199
- 198, 198, 198, 198, 0, 0, 0, 0 },
- { 54, 54, 54, 54, 54, 55, 48, 63, // 200
- 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 63, 48, 55, // 201
- 54, 54, 54, 54, 54, 54, 54, 54 },
- { 54, 54, 54, 54, 54, 247, 0, 255, // 202
- 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 255, 0, 247, // 203
- 54, 54, 54, 54, 54, 54, 54, 54 },
- { 54, 54, 54, 54, 54, 55, 48, 55, // 204
- 54, 54, 54, 54, 54, 54, 54, 54 },
- { 0, 0, 0, 0, 0, 255, 0, 255, // 205
- 0, 0, 0, 0, 0, 0, 0, 0 },
- { 54, 54, 54, 54, 54, 247, 0, 247, // 206
- 54, 54, 54, 54, 54, 54, 54, 54 },
- { 0, 0, 0, 0, 198, 124, 198, 198, // 207
- 198, 198, 124, 198, 0, 0, 0, 0 },
- { 0, 0, 52, 24, 44, 6, 62, 102, // 208
- 102, 102, 102, 60, 0, 0, 0, 0 },
- { 0, 0, 248, 108, 102, 102, 246, 102, // 209
- 102, 102, 108, 248, 0, 0, 0, 0 },
- { 56, 108, 0, 254, 102, 98, 104, 120, // 210
- 104, 98, 102, 254, 0, 0, 0, 0 },
- { 0, 198, 0, 254, 102, 98, 104, 120, // 211
- 104, 98, 102, 254, 0, 0, 0, 0 },
- { 48, 24, 0, 254, 102, 98, 104, 120, // 212
- 104, 98, 102, 254, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 56, 24, 24, // 213
- 24, 24, 24, 60, 0, 0, 0, 0 },
- { 12, 24, 0, 60, 24, 24, 24, 24, // 214
- 24, 24, 24, 60, 0, 0, 0, 0 },
- { 60, 102, 0, 60, 24, 24, 24, 24, // 215
- 24, 24, 24, 60, 0, 0, 0, 0 },
- { 0, 102, 0, 60, 24, 24, 24, 24, // 216
- 24, 24, 24, 60, 0, 0, 0, 0 },
- { 24, 24, 24, 24, 24, 24, 24, 248, // 217
- 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 31, // 218
- 24, 24, 24, 24, 24, 24, 24, 24 },
- { 255, 255, 255, 255, 255, 255, 255, 255, // 219
- 255, 255, 255, 255, 255, 255, 255, 255 },
- { 0, 0, 0, 0, 0, 0, 0, 255, // 220
- 255, 255, 255, 255, 255, 255, 255, 255 },
- { 0, 24, 24, 24, 24, 24, 0, 0, // 221
- 24, 24, 24, 24, 24, 0, 0, 0 },
- { 48, 24, 0, 60, 24, 24, 24, 24, // 222
- 24, 24, 24, 60, 0, 0, 0, 0 },
- { 255, 255, 255, 255, 255, 255, 255, 0, // 223
- 0, 0, 0, 0, 0, 0, 0, 0 },
- { 24, 48, 0, 124, 198, 198, 198, 198, // 224
- 198, 198, 198, 124, 0, 0, 0, 0 },
- { 0, 0, 120, 204, 204, 204, 216, 204, // 225
- 198, 198, 198, 204, 0, 0, 0, 0 },
- { 56, 108, 0, 124, 198, 198, 198, 198, // 226
- 198, 198, 198, 124, 0, 0, 0, 0 },
- { 48, 24, 0, 124, 198, 198, 198, 198, // 227
- 198, 198, 198, 124, 0, 0, 0, 0 },
- { 0, 0, 118, 220, 0, 124, 198, 198, // 228
- 198, 198, 198, 124, 0, 0, 0, 0 },
- { 118, 220, 0, 124, 198, 198, 198, 198, // 229
- 198, 198, 198, 124, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 102, 102, 102, // 230
- 102, 102, 102, 124, 96, 96, 192, 0 },
- { 0, 0, 224, 96, 96, 124, 102, 102, // 231
- 102, 102, 102, 124, 96, 96, 240, 0 },
- { 0, 0, 240, 96, 124, 102, 102, 102, // 232
- 102, 124, 96, 240, 0, 0, 0, 0 },
- { 24, 48, 0, 198, 198, 198, 198, 198, // 233
- 198, 198, 198, 124, 0, 0, 0, 0 },
- { 56, 108, 0, 198, 198, 198, 198, 198, // 234
- 198, 198, 198, 124, 0, 0, 0, 0 },
- { 48, 24, 0, 198, 198, 198, 198, 198, // 235
- 198, 198, 198, 124, 0, 0, 0, 0 },
- { 0, 12, 24, 48, 0, 198, 198, 198, // 236
- 198, 198, 198, 126, 6, 12, 248, 0 },
- { 12, 24, 0, 102, 102, 102, 102, 60, // 237
- 24, 24, 24, 60, 0, 0, 0, 0 },
- { 0, 255, 0, 0, 0, 0, 0, 0, // 238
- 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 12, 24, 48, 0, 0, 0, 0, // 239
- 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 254, // 240
- 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 24, 24, 126, 24, // 241
- 24, 0, 0, 126, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, // 242
- 0, 0, 0, 0, 255, 0, 255, 0 },
- { 0, 224, 48, 98, 54, 236, 24, 48, // 243
- 102, 206, 154, 63, 6, 6, 0, 0 },
- { 0, 0, 127, 219, 219, 219, 123, 27, // 244
- 27, 27, 27, 27, 0, 0, 0, 0 },
- { 0, 124, 198, 96, 56, 108, 198, 198, // 245
- 108, 56, 12, 198, 124, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 24, 0, 126, // 246
- 0, 24, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, // 247
- 0, 0, 0, 24, 12, 120, 0, 0 },
- { 0, 56, 108, 108, 56, 0, 0, 0, // 248
- 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 198, 0, 0, 0, 0, 0, 0, // 249
- 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 24, // 250
- 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 24, 56, 24, 24, 24, 60, 0, // 251
- 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 124, 6, 60, 6, 6, 124, 0, // 252
- 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 60, 102, 12, 24, 50, 126, 0, // 253
- 0, 0, 0, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 126, 126, 126, 126, // 254
- 126, 126, 126, 0, 0, 0, 0, 0 },
- { 0, 0, 0, 0, 0, 0, 0, 0, // 255
- 0, 0, 0, 0, 0, 0, 0, 0 }};
-
-unsigned char sdl_font8x8[256][8] = {
- { 0, 0, 0, 0, 0, 0, 0, 0 }, // 0
- { 126, 129, 165, 129, 189, 153, 129, 126 }, // 1
- { 126, 255, 219, 255, 195, 231, 255, 126 }, // 2
- { 108, 254, 254, 254, 124, 56, 16, 0 }, // 3
- { 16, 56, 124, 254, 124, 56, 16, 0 }, // 4
- { 56, 124, 56, 254, 254, 214, 16, 56 }, // 5
- { 16, 56, 124, 254, 254, 124, 16, 56 }, // 6
- { 0, 0, 24, 60, 60, 24, 0, 0 }, // 7
- { 255, 255, 231, 195, 195, 231, 255, 255 }, // 8
- { 0, 60, 102, 66, 66, 102, 60, 0 }, // 9
- { 255, 195, 153, 189, 189, 153, 195, 255 }, // 10
- { 15, 7, 15, 125, 204, 204, 204, 120 }, // 11
- { 60, 102, 102, 102, 60, 24, 126, 24 }, // 12
- { 63, 51, 63, 48, 48, 112, 240, 224 }, // 13
- { 127, 99, 127, 99, 99, 103, 230, 192 }, // 14
- { 24, 219, 60, 231, 231, 60, 219, 24 }, // 15
- { 128, 224, 248, 254, 248, 224, 128, 0 }, // 16
- { 2, 14, 62, 254, 62, 14, 2, 0 }, // 17
- { 24, 60, 126, 24, 24, 126, 60, 24 }, // 18
- { 102, 102, 102, 102, 102, 0, 102, 0 }, // 19
- { 127, 219, 219, 123, 27, 27, 27, 0 }, // 20
- { 62, 97, 60, 102, 102, 60, 134, 124 }, // 21
- { 0, 0, 0, 0, 126, 126, 126, 0 }, // 22
- { 24, 60, 126, 24, 126, 60, 24, 255 }, // 23
- { 24, 60, 126, 24, 24, 24, 24, 0 }, // 24
- { 24, 24, 24, 24, 126, 60, 24, 0 }, // 25
- { 0, 24, 12, 254, 12, 24, 0, 0 }, // 26
- { 0, 48, 96, 254, 96, 48, 0, 0 }, // 27
- { 0, 0, 192, 192, 192, 254, 0, 0 }, // 28
- { 0, 36, 102, 255, 102, 36, 0, 0 }, // 29
- { 0, 24, 60, 126, 255, 255, 0, 0 }, // 30
- { 0, 255, 255, 126, 60, 24, 0, 0 }, // 31
- { 0, 0, 0, 0, 0, 0, 0, 0 }, // 32
- { 24, 60, 60, 24, 24, 0, 24, 0 }, // 33
- { 102, 102, 36, 0, 0, 0, 0, 0 }, // 34
- { 108, 108, 254, 108, 254, 108, 108, 0 }, // 35
- { 24, 62, 96, 60, 6, 124, 24, 0 }, // 36
- { 0, 198, 204, 24, 48, 102, 198, 0 }, // 37
- { 56, 108, 56, 118, 220, 204, 118, 0 }, // 38
- { 24, 24, 48, 0, 0, 0, 0, 0 }, // 39
- { 12, 24, 48, 48, 48, 24, 12, 0 }, // 40
- { 48, 24, 12, 12, 12, 24, 48, 0 }, // 41
- { 0, 102, 60, 231, 60, 102, 0, 0 }, // 42
- { 0, 24, 24, 126, 24, 24, 0, 0 }, // 43
- { 0, 0, 0, 0, 0, 24, 24, 48 }, // 44
- { 0, 0, 0, 126, 0, 0, 0, 0 }, // 45
- { 0, 0, 0, 0, 0, 24, 24, 0 }, // 46
- { 6, 12, 24, 48, 96, 192, 128, 0 }, // 47
- { 124, 198, 206, 222, 246, 230, 124, 0 }, // 48
- { 24, 56, 24, 24, 24, 24, 126, 0 }, // 49
- { 124, 198, 6, 28, 48, 102, 254, 0 }, // 50
- { 124, 198, 6, 60, 6, 198, 124, 0 }, // 51
- { 28, 60, 108, 204, 254, 12, 30, 0 }, // 52
- { 254, 192, 192, 252, 6, 198, 124, 0 }, // 53
- { 56, 96, 192, 252, 198, 198, 124, 0 }, // 54
- { 254, 198, 12, 24, 48, 48, 48, 0 }, // 55
- { 124, 198, 198, 124, 198, 198, 124, 0 }, // 56
- { 124, 198, 198, 126, 6, 12, 120, 0 }, // 57
- { 0, 24, 24, 0, 0, 24, 24, 0 }, // 58
- { 0, 24, 24, 0, 0, 24, 24, 48 }, // 59
- { 6, 12, 24, 48, 24, 12, 6, 0 }, // 60
- { 0, 0, 126, 0, 0, 126, 0, 0 }, // 61
- { 96, 48, 24, 12, 24, 48, 96, 0 }, // 62
- { 124, 198, 12, 24, 24, 0, 24, 0 }, // 63
- { 124, 198, 222, 222, 222, 192, 120, 0 }, // 64
- { 56, 108, 198, 254, 198, 198, 198, 0 }, // 65
- { 252, 102, 102, 124, 102, 102, 252, 0 }, // 66
- { 60, 102, 192, 192, 192, 102, 60, 0 }, // 67
- { 248, 108, 102, 102, 102, 108, 248, 0 }, // 68
- { 254, 98, 104, 120, 104, 98, 254, 0 }, // 69
- { 254, 98, 104, 120, 104, 96, 240, 0 }, // 70
- { 60, 102, 192, 192, 206, 102, 58, 0 }, // 71
- { 198, 198, 198, 254, 198, 198, 198, 0 }, // 72
- { 60, 24, 24, 24, 24, 24, 60, 0 }, // 73
- { 30, 12, 12, 12, 204, 204, 120, 0 }, // 74
- { 230, 102, 108, 120, 108, 102, 230, 0 }, // 75
- { 240, 96, 96, 96, 98, 102, 254, 0 }, // 76
- { 198, 238, 254, 254, 214, 198, 198, 0 }, // 77
- { 198, 230, 246, 222, 206, 198, 198, 0 }, // 78
- { 124, 198, 198, 198, 198, 198, 124, 0 }, // 79
- { 252, 102, 102, 124, 96, 96, 240, 0 }, // 80
- { 124, 198, 198, 198, 198, 206, 124, 14 }, // 81
- { 252, 102, 102, 124, 108, 102, 230, 0 }, // 82
- { 60, 102, 48, 24, 12, 102, 60, 0 }, // 83
- { 126, 126, 90, 24, 24, 24, 60, 0 }, // 84
- { 198, 198, 198, 198, 198, 198, 124, 0 }, // 85
- { 198, 198, 198, 198, 198, 108, 56, 0 }, // 86
- { 198, 198, 198, 214, 214, 254, 108, 0 }, // 87
- { 198, 198, 108, 56, 108, 198, 198, 0 }, // 88
- { 102, 102, 102, 60, 24, 24, 60, 0 }, // 89
- { 254, 198, 140, 24, 50, 102, 254, 0 }, // 90
- { 60, 48, 48, 48, 48, 48, 60, 0 }, // 91
- { 192, 96, 48, 24, 12, 6, 2, 0 }, // 92
- { 60, 12, 12, 12, 12, 12, 60, 0 }, // 93
- { 16, 56, 108, 198, 0, 0, 0, 0 }, // 94
- { 0, 0, 0, 0, 0, 0, 0, 255 }, // 95
- { 48, 24, 12, 0, 0, 0, 0, 0 }, // 96
- { 0, 0, 120, 12, 124, 204, 118, 0 }, // 97
- { 224, 96, 124, 102, 102, 102, 220, 0 }, // 98
- { 0, 0, 124, 198, 192, 198, 124, 0 }, // 99
- { 28, 12, 124, 204, 204, 204, 118, 0 }, // 100
- { 0, 0, 124, 198, 254, 192, 124, 0 }, // 101
- { 60, 102, 96, 248, 96, 96, 240, 0 }, // 102
- { 0, 0, 118, 204, 204, 124, 12, 248 }, // 103
- { 224, 96, 108, 118, 102, 102, 230, 0 }, // 104
- { 24, 0, 56, 24, 24, 24, 60, 0 }, // 105
- { 6, 0, 6, 6, 6, 102, 102, 60 }, // 106
- { 224, 96, 102, 108, 120, 108, 230, 0 }, // 107
- { 56, 24, 24, 24, 24, 24, 60, 0 }, // 108
- { 0, 0, 236, 254, 214, 214, 214, 0 }, // 109
- { 0, 0, 220, 102, 102, 102, 102, 0 }, // 110
- { 0, 0, 124, 198, 198, 198, 124, 0 }, // 111
- { 0, 0, 220, 102, 102, 124, 96, 240 }, // 112
- { 0, 0, 118, 204, 204, 124, 12, 30 }, // 113
- { 0, 0, 220, 118, 96, 96, 240, 0 }, // 114
- { 0, 0, 126, 192, 124, 6, 252, 0 }, // 115
- { 48, 48, 252, 48, 48, 54, 28, 0 }, // 116
- { 0, 0, 204, 204, 204, 204, 118, 0 }, // 117
- { 0, 0, 198, 198, 198, 108, 56, 0 }, // 118
- { 0, 0, 198, 214, 214, 254, 108, 0 }, // 119
- { 0, 0, 198, 108, 56, 108, 198, 0 }, // 120
- { 0, 0, 198, 198, 198, 126, 6, 252 }, // 121
- { 0, 0, 126, 76, 24, 50, 126, 0 }, // 122
- { 14, 24, 24, 112, 24, 24, 14, 0 }, // 123
- { 24, 24, 24, 24, 24, 24, 24, 0 }, // 124
- { 112, 24, 24, 14, 24, 24, 112, 0 }, // 125
- { 118, 220, 0, 0, 0, 0, 0, 0 }, // 126
- { 0, 16, 56, 108, 198, 198, 254, 0 }, // 127
- { 124, 198, 192, 192, 198, 124, 12, 120 }, // 128
- { 204, 0, 204, 204, 204, 204, 118, 0 }, // 129
- { 12, 24, 124, 198, 254, 192, 124, 0 }, // 130
- { 124, 130, 120, 12, 124, 204, 118, 0 }, // 131
- { 198, 0, 120, 12, 124, 204, 118, 0 }, // 132
- { 48, 24, 120, 12, 124, 204, 118, 0 }, // 133
- { 48, 48, 120, 12, 124, 204, 118, 0 }, // 134
- { 0, 0, 126, 192, 192, 126, 12, 56 }, // 135
- { 124, 130, 124, 198, 254, 192, 124, 0 }, // 136
- { 198, 0, 124, 198, 254, 192, 124, 0 }, // 137
- { 48, 24, 124, 198, 254, 192, 124, 0 }, // 138
- { 102, 0, 56, 24, 24, 24, 60, 0 }, // 139
- { 124, 130, 56, 24, 24, 24, 60, 0 }, // 140
- { 48, 24, 0, 56, 24, 24, 60, 0 }, // 141
- { 198, 56, 108, 198, 254, 198, 198, 0 }, // 142
- { 56, 108, 124, 198, 254, 198, 198, 0 }, // 143
- { 24, 48, 254, 192, 248, 192, 254, 0 }, // 144
- { 0, 0, 126, 18, 254, 144, 254, 0 }, // 145
- { 62, 108, 204, 254, 204, 204, 206, 0 }, // 146
- { 124, 130, 124, 198, 198, 198, 124, 0 }, // 147
- { 198, 0, 124, 198, 198, 198, 124, 0 }, // 148
- { 48, 24, 124, 198, 198, 198, 124, 0 }, // 149
- { 120, 132, 0, 204, 204, 204, 118, 0 }, // 150
- { 96, 48, 204, 204, 204, 204, 118, 0 }, // 151
- { 198, 0, 198, 198, 198, 126, 6, 252 }, // 152
- { 198, 56, 108, 198, 198, 108, 56, 0 }, // 153
- { 198, 0, 198, 198, 198, 198, 124, 0 }, // 154
- { 0, 2, 124, 206, 214, 230, 124, 128 }, // 155
- { 56, 108, 100, 240, 96, 102, 252, 0 }, // 156
- { 58, 108, 206, 214, 230, 108, 184, 0 }, // 157
- { 0, 198, 108, 56, 108, 198, 0, 0 }, // 158
- { 14, 27, 24, 60, 24, 216, 112, 0 }, // 159
- { 24, 48, 120, 12, 124, 204, 118, 0 }, // 160
- { 12, 24, 0, 56, 24, 24, 60, 0 }, // 161
- { 12, 24, 124, 198, 198, 198, 124, 0 }, // 162
- { 24, 48, 204, 204, 204, 204, 118, 0 }, // 163
- { 118, 220, 0, 220, 102, 102, 102, 0 }, // 164
- { 118, 220, 0, 230, 246, 222, 206, 0 }, // 165
- { 60, 108, 108, 62, 0, 126, 0, 0 }, // 166
- { 56, 108, 108, 56, 0, 124, 0, 0 }, // 167
- { 24, 0, 24, 24, 48, 99, 62, 0 }, // 168
- { 126, 129, 185, 165, 185, 165, 129, 126 }, // 169
- { 0, 0, 0, 254, 6, 6, 0, 0 }, // 170
- { 99, 230, 108, 126, 51, 102, 204, 15 }, // 171
- { 99, 230, 108, 122, 54, 106, 223, 6 }, // 172
- { 24, 0, 24, 24, 60, 60, 24, 0 }, // 173
- { 0, 51, 102, 204, 102, 51, 0, 0 }, // 174
- { 0, 204, 102, 51, 102, 204, 0, 0 }, // 175
- { 34, 136, 34, 136, 34, 136, 34, 136 }, // 176
- { 85, 170, 85, 170, 85, 170, 85, 170 }, // 177
- { 119, 221, 119, 221, 119, 221, 119, 221 }, // 178
- { 24, 24, 24, 24, 24, 24, 24, 24 }, // 179
- { 24, 24, 56, 248, 56, 24, 24, 24 }, // 180
- { 48, 96, 56, 108, 198, 254, 198, 0 }, // 181
- { 124, 130, 56, 108, 198, 254, 198, 0 }, // 182
- { 24, 12, 56, 108, 198, 254, 198, 0 }, // 183
- { 126, 129, 157, 161, 161, 157, 129, 126 }, // 184
- { 54, 54, 246, 6, 246, 54, 54, 54 }, // 185
- { 54, 54, 54, 54, 54, 54, 54, 54 }, // 186
- { 0, 0, 254, 6, 246, 54, 54, 54 }, // 187
- { 54, 54, 246, 6, 254, 0, 0, 0 }, // 188
- { 24, 24, 126, 192, 192, 126, 24, 24 }, // 189
- { 102, 102, 60, 126, 24, 126, 24, 24 }, // 190
- { 0, 0, 0, 240, 56, 24, 24, 24 }, // 191
- { 24, 24, 28, 15, 0, 0, 0, 0 }, // 192
- { 24, 24, 60, 255, 0, 0, 0, 0 }, // 193
- { 0, 0, 0, 255, 60, 24, 24, 24 }, // 194
- { 48, 48, 56, 63, 56, 48, 48, 48 }, // 195
- { 0, 0, 0, 255, 0, 0, 0, 0 }, // 196
- { 24, 24, 24, 60, 231, 60, 24, 24 }, // 197
- { 240, 120, 120, 120, 60, 60, 60, 28 }, // 198
- { 30, 60, 60, 60, 120, 120, 120, 112 }, // 199
- { 15, 63, 63, 120, 120, 0, 1, 3 }, // 200
- { 192, 224, 240, 240, 240, 240, 240, 224 }, // 201
- { 0, 0, 0, 0, 0, 0, 0, 0 }, // 202
- { 0, 0, 0, 0, 0, 0, 0, 0 }, // 203
- { 30, 30, 14, 15, 15, 7, 7, 0 }, // 204
- { 240, 240, 224, 224, 192, 192, 192, 0 }, // 205
- { 6, 13, 27, 55, 47, 127, 126, 30 }, // 206
- { 0, 252, 255, 255, 143, 119, 243, 3 }, // 207
- { 0, 1, 7, 143, 143, 207, 207, 199 }, // 208
- { 0, 248, 254, 254, 31, 15, 192, 248 }, // 209
- { 0, 0, 0, 0, 0, 0, 0, 0 }, // 210
- { 0, 0, 0, 0, 0, 0, 0, 0 }, // 211
- { 30, 30, 30, 31, 15, 7, 7, 1 }, // 212
- { 3, 3, 3, 7, 143, 255, 254, 252 }, // 213
- { 195, 192, 192, 207, 143, 7, 7, 1 }, // 214
- { 254, 255, 31, 15, 143, 254, 254, 248 }, // 215
- { 102, 0, 60, 24, 24, 24, 60, 0 }, // 216
- { 24, 24, 56, 240, 0, 0, 0, 0 }, // 217
- { 0, 0, 0, 15, 28, 24, 24, 24 }, // 218
- { 255, 255, 255, 255, 255, 255, 255, 255 }, // 219
- { 0, 0, 0, 0, 255, 255, 255, 255 }, // 220
- { 24, 24, 24, 0, 0, 24, 24, 24 }, // 221
- { 48, 24, 60, 24, 24, 24, 60, 0 }, // 222
- { 255, 255, 255, 255, 0, 0, 0, 0 }, // 223
- { 0, 0, 0, 0, 0, 0, 0, 255 }, // 224
- { 0, 0, 0, 0, 0, 255, 0, 255 }, // 225
- { 0, 0, 0, 255, 0, 255, 0, 255 }, // 226
- { 0, 255, 0, 255, 0, 255, 0, 255 }, // 227
- { 0, 255, 0, 255, 0, 255, 0, 0 }, // 228
- { 0, 255, 0, 255, 0, 0, 0, 0 }, // 229
- { 0, 255, 0, 0, 0, 0, 0, 0 }, // 230
- { 224, 128, 0, 0, 0, 0, 128, 224 }, // 231
- { 248, 254, 255, 255, 255, 255, 254, 248 }, // 232
- { 24, 48, 198, 198, 198, 198, 124, 0 }, // 233
- { 124, 130, 0, 198, 198, 198, 124, 0 }, // 234
- { 96, 48, 198, 198, 198, 198, 124, 0 }, // 235
- { 24, 48, 198, 198, 198, 126, 6, 252 }, // 236
- { 12, 24, 102, 102, 60, 24, 60, 0 }, // 237
- { 255, 0, 0, 0, 0, 0, 0, 0 }, // 238
- { 12, 24, 48, 0, 0, 0, 0, 0 }, // 239
- { 0, 0, 0, 126, 0, 0, 0, 0 }, // 240
- { 24, 24, 126, 24, 24, 0, 126, 0 }, // 241
- { 0, 0, 0, 0, 0, 255, 0, 255 }, // 242
- { 225, 50, 228, 58, 246, 42, 95, 134 }, // 243
- { 127, 219, 219, 123, 27, 27, 27, 0 }, // 244
- { 62, 97, 60, 102, 102, 60, 134, 124 }, // 245
- { 0, 24, 0, 126, 0, 24, 0, 0 }, // 246
- { 0, 0, 0, 0, 0, 24, 12, 56 }, // 247
- { 56, 108, 108, 56, 0, 0, 0, 0 }, // 248
- { 0, 198, 0, 0, 0, 0, 0, 0 }, // 249
- { 0, 0, 0, 24, 0, 0, 0, 0 }, // 250
- { 24, 56, 24, 24, 60, 0, 0, 0 }, // 251
- { 120, 12, 56, 12, 120, 0, 0, 0 }, // 252
- { 120, 12, 24, 48, 124, 0, 0, 0 }, // 253
- { 0, 0, 60, 60, 60, 60, 0, 0 }, // 254
- { 0, 0, 0, 0, 0, 0, 0, 0 }}; // 255
-
-/*
-unsigned char sdl_palette[256][3] = {
- { 0, 0, 0 }, // 0
- { 0, 0, 168 }, // 1
- { 0, 168, 0 }, // 2
- { 0, 168, 168 }, // 3
- { 168, 0, 0 }, // 4
- { 168, 0, 168 }, // 5
- { 168, 84, 0 }, // 6
- { 168, 168, 168 }, // 7
- { 84, 84, 84 }, // 8
- { 84, 84, 252 }, // 9
- { 84, 252, 84 }, // 10
- { 84, 252, 252 }, // 11
- { 252, 84, 84 }, // 12
- { 252, 84, 252 }, // 13
- { 252, 252, 84 }, // 14
- { 252, 252, 252 }, // 15
- { 0, 0, 0 }, // 16
- { 20, 20, 20 }, // 17
- { 32, 32, 32 }, // 18
- { 44, 44, 44 }, // 19
- { 56, 56, 56 }, // 20
- { 68, 68, 68 }, // 21
- { 80, 80, 80 }, // 22
- { 96, 96, 96 }, // 23
- { 112, 112, 112 }, // 24
- { 128, 128, 128 }, // 25
- { 144, 144, 144 }, // 26
- { 160, 160, 160 }, // 27
- { 180, 180, 180 }, // 28
- { 200, 200, 200 }, // 29
- { 224, 224, 224 }, // 30
- { 252, 252, 252 }, // 31
- { 0, 0, 252 }, // 32
- { 64, 0, 252 }, // 33
- { 124, 0, 252 }, // 34
- { 188, 0, 252 }, // 35
- { 252, 0, 252 }, // 36
- { 252, 0, 188 }, // 37
- { 252, 0, 124 }, // 38
- { 252, 0, 64 }, // 39
- { 252, 0, 0 }, // 40
- { 252, 64, 0 }, // 41
- { 252, 124, 0 }, // 42
- { 252, 188, 0 }, // 43
- { 252, 252, 0 }, // 44
- { 188, 252, 0 }, // 45
- { 124, 252, 0 }, // 46
- { 64, 252, 0 }, // 47
- { 0, 252, 0 }, // 48
- { 0, 252, 64 }, // 49
- { 0, 252, 124 }, // 50
- { 0, 252, 188 }, // 51
- { 0, 252, 252 }, // 52
- { 0, 188, 252 }, // 53
- { 0, 124, 252 }, // 54
- { 0, 64, 252 }, // 55
- { 124, 124, 252 }, // 56
- { 156, 124, 252 }, // 57
- { 188, 124, 252 }, // 58
- { 220, 124, 252 }, // 59
- { 252, 124, 252 }, // 60
- { 252, 124, 220 }, // 61
- { 252, 124, 188 }, // 62
- { 252, 124, 156 }, // 63
- { 252, 124, 124 }, // 64
- { 252, 156, 124 }, // 65
- { 252, 188, 124 }, // 66
- { 252, 220, 124 }, // 67
- { 252, 252, 124 }, // 68
- { 220, 252, 124 }, // 69
- { 188, 252, 124 }, // 70
- { 156, 252, 124 }, // 71
- { 124, 252, 124 }, // 72
- { 124, 252, 156 }, // 73
- { 124, 252, 188 }, // 74
- { 124, 252, 220 }, // 75
- { 124, 252, 252 }, // 76
- { 124, 220, 252 }, // 77
- { 124, 188, 252 }, // 78
- { 124, 156, 252 }, // 79
- { 180, 180, 252 }, // 80
- { 196, 180, 252 }, // 81
- { 216, 180, 252 }, // 82
- { 232, 180, 252 }, // 83
- { 252, 180, 252 }, // 84
- { 252, 180, 232 }, // 85
- { 252, 180, 216 }, // 86
- { 252, 180, 196 }, // 87
- { 252, 180, 180 }, // 88
- { 252, 196, 180 }, // 89
- { 252, 216, 180 }, // 90
- { 252, 232, 180 }, // 91
- { 252, 252, 180 }, // 92
- { 232, 252, 180 }, // 93
- { 216, 252, 180 }, // 94
- { 196, 252, 180 }, // 95
- { 180, 252, 180 }, // 96
- { 180, 252, 196 }, // 97
- { 180, 252, 216 }, // 98
- { 180, 252, 232 }, // 99
- { 180, 252, 252 }, // 100
- { 180, 232, 252 }, // 101
- { 180, 216, 252 }, // 102
- { 180, 196, 252 }, // 103
- { 0, 0, 112 }, // 104
- { 28, 0, 112 }, // 105
- { 56, 0, 112 }, // 106
- { 84, 0, 112 }, // 107
- { 112, 0, 112 }, // 108
- { 112, 0, 84 }, // 109
- { 112, 0, 56 }, // 110
- { 112, 0, 28 }, // 111
- { 112, 0, 0 }, // 112
- { 112, 28, 0 }, // 113
- { 112, 56, 0 }, // 114
- { 112, 84, 0 }, // 115
- { 112, 112, 0 }, // 116
- { 84, 112, 0 }, // 117
- { 56, 112, 0 }, // 118
- { 28, 112, 0 }, // 119
- { 0, 112, 0 }, // 120
- { 0, 112, 28 }, // 121
- { 0, 112, 56 }, // 122
- { 0, 112, 84 }, // 123
- { 0, 112, 112 }, // 124
- { 0, 84, 112 }, // 125
- { 0, 56, 112 }, // 126
- { 0, 28, 112 }, // 127
- { 56, 56, 112 }, // 128
- { 68, 56, 112 }, // 129
- { 84, 56, 112 }, // 130
- { 96, 56, 112 }, // 131
- { 112, 56, 112 }, // 132
- { 112, 56, 96 }, // 133
- { 112, 56, 84 }, // 134
- { 112, 56, 68 }, // 135
- { 112, 56, 56 }, // 136
- { 112, 68, 56 }, // 137
- { 112, 84, 56 }, // 138
- { 112, 96, 56 }, // 139
- { 112, 112, 56 }, // 140
- { 96, 112, 56 }, // 141
- { 84, 112, 56 }, // 142
- { 68, 112, 56 }, // 143
- { 56, 112, 56 }, // 144
- { 56, 112, 68 }, // 145
- { 56, 112, 84 }, // 146
- { 56, 112, 96 }, // 147
- { 56, 112, 112 }, // 148
- { 56, 96, 112 }, // 149
- { 56, 84, 112 }, // 150
- { 56, 68, 112 }, // 151
- { 80, 80, 112 }, // 152
- { 88, 80, 112 }, // 153
- { 96, 80, 112 }, // 154
- { 104, 80, 112 }, // 155
- { 112, 80, 112 }, // 156
- { 112, 80, 104 }, // 157
- { 112, 80, 96 }, // 158
- { 112, 80, 88 }, // 159
- { 112, 80, 80 }, // 160
- { 112, 88, 80 }, // 161
- { 112, 96, 80 }, // 162
- { 112, 104, 80 }, // 163
- { 112, 112, 80 }, // 164
- { 104, 112, 80 }, // 165
- { 96, 112, 80 }, // 166
- { 88, 112, 80 }, // 167
- { 80, 112, 80 }, // 168
- { 80, 112, 88 }, // 169
- { 80, 112, 96 }, // 170
- { 80, 112, 104 }, // 171
- { 80, 112, 112 }, // 172
- { 80, 104, 112 }, // 173
- { 80, 96, 112 }, // 174
- { 80, 88, 112 }, // 175
- { 0, 0, 64 }, // 176
- { 16, 0, 64 }, // 177
- { 32, 0, 64 }, // 178
- { 48, 0, 64 }, // 179
- { 64, 0, 64 }, // 180
- { 64, 0, 48 }, // 181
- { 64, 0, 32 }, // 182
- { 64, 0, 16 }, // 183
- { 64, 0, 0 }, // 184
- { 64, 16, 0 }, // 185
- { 64, 32, 0 }, // 186
- { 64, 48, 0 }, // 187
- { 64, 64, 0 }, // 188
- { 48, 64, 0 }, // 189
- { 32, 64, 0 }, // 190
- { 16, 64, 0 }, // 191
- { 0, 64, 0 }, // 192
- { 0, 64, 16 }, // 193
- { 0, 64, 32 }, // 194
- { 0, 64, 48 }, // 195
- { 0, 64, 64 }, // 196
- { 0, 48, 64 }, // 197
- { 0, 32, 64 }, // 198
- { 0, 16, 64 }, // 199
- { 32, 32, 64 }, // 200
- { 40, 32, 64 }, // 201
- { 48, 32, 64 }, // 202
- { 56, 32, 64 }, // 203
- { 64, 32, 64 }, // 204
- { 64, 32, 56 }, // 205
- { 64, 32, 48 }, // 206
- { 64, 32, 40 }, // 207
- { 64, 32, 32 }, // 208
- { 64, 40, 32 }, // 209
- { 64, 48, 32 }, // 210
- { 64, 56, 32 }, // 211
- { 64, 64, 32 }, // 212
- { 56, 64, 32 }, // 213
- { 48, 64, 32 }, // 214
- { 40, 64, 32 }, // 215
- { 32, 64, 32 }, // 216
- { 32, 64, 40 }, // 217
- { 32, 64, 48 }, // 218
- { 32, 64, 56 }, // 219
- { 32, 64, 64 }, // 220
- { 32, 56, 64 }, // 221
- { 32, 48, 64 }, // 222
- { 32, 40, 64 }, // 223
- { 44, 44, 64 }, // 224
- { 48, 44, 64 }, // 225
- { 52, 44, 64 }, // 226
- { 60, 44, 64 }, // 227
- { 64, 44, 64 }, // 228
- { 64, 44, 60 }, // 229
- { 64, 44, 52 }, // 230
- { 64, 44, 48 }, // 231
- { 64, 44, 44 }, // 232
- { 64, 48, 44 }, // 233
- { 64, 52, 44 }, // 234
- { 64, 60, 44 }, // 235
- { 64, 64, 44 }, // 236
- { 60, 64, 44 }, // 237
- { 52, 64, 44 }, // 238
- { 48, 64, 44 }, // 239
- { 44, 64, 44 }, // 240
- { 44, 64, 48 }, // 241
- { 44, 64, 52 }, // 242
- { 44, 64, 60 }, // 243
- { 44, 64, 64 }, // 244
- { 44, 60, 64 }, // 245
- { 44, 52, 64 }, // 246
- { 44, 48, 64 }, // 247
- { 0, 0, 0 }, // 248
- { 0, 0, 0 }, // 249
- { 0, 0, 0 }, // 250
- { 0, 0, 0 }, // 251
- { 0, 0, 0 }, // 252
- { 0, 0, 0 }, // 253
- { 0, 0, 0 }, // 254
- { 112, 97, 108 }}; // 255
-*/
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: sdlkeys.h,v 1.2 2002/10/24 21:06:32 bdenney Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// This file is simply a list of SDL key symbols taken from <SDL/SDL_keysym.h>.
-// The order in this file is not important. In sdl.cc, DEF_SDL_KEY() is
-// defined as a macro and then it includes this file to fill in all the data in
-// its key mapping table.
-//
-// The symbols, such as SDLK_RETURN, are used for two purposes. They
-// are converted into a string (by the # operator in processor), which is
-// compared to the host key name in the keymap file. Also, the value of
-// the symbol is inserted into the key mapping table. Then the value is
-// compared with the keysym field of each key up/down event as it arrives.
-//
-// If you get undefined symbol errors in this file, it must mean that
-// your SDL library version doesn't define those same SDLK_* symbols in
-// <SDL/SDL_keysym.h>. You can't fix it with #ifdef SDLK_SYM because
-// they are enums, so you'll just have to comment out the offending line.
-// The list was generated using symbols from SDL 1.2.3.
-
-DEF_SDL_KEY( SDLK_UNKNOWN )
-DEF_SDL_KEY( SDLK_FIRST )
-DEF_SDL_KEY( SDLK_BACKSPACE )
-DEF_SDL_KEY( SDLK_TAB )
-DEF_SDL_KEY( SDLK_CLEAR )
-DEF_SDL_KEY( SDLK_RETURN )
-DEF_SDL_KEY( SDLK_PAUSE )
-DEF_SDL_KEY( SDLK_ESCAPE )
-DEF_SDL_KEY( SDLK_SPACE )
-DEF_SDL_KEY( SDLK_EXCLAIM )
-DEF_SDL_KEY( SDLK_QUOTEDBL )
-DEF_SDL_KEY( SDLK_HASH )
-DEF_SDL_KEY( SDLK_DOLLAR )
-DEF_SDL_KEY( SDLK_AMPERSAND )
-DEF_SDL_KEY( SDLK_QUOTE )
-DEF_SDL_KEY( SDLK_LEFTPAREN )
-DEF_SDL_KEY( SDLK_RIGHTPAREN )
-DEF_SDL_KEY( SDLK_ASTERISK )
-DEF_SDL_KEY( SDLK_PLUS )
-DEF_SDL_KEY( SDLK_COMMA )
-DEF_SDL_KEY( SDLK_MINUS )
-DEF_SDL_KEY( SDLK_PERIOD )
-DEF_SDL_KEY( SDLK_SLASH )
-DEF_SDL_KEY( SDLK_0 )
-DEF_SDL_KEY( SDLK_1 )
-DEF_SDL_KEY( SDLK_2 )
-DEF_SDL_KEY( SDLK_3 )
-DEF_SDL_KEY( SDLK_4 )
-DEF_SDL_KEY( SDLK_5 )
-DEF_SDL_KEY( SDLK_6 )
-DEF_SDL_KEY( SDLK_7 )
-DEF_SDL_KEY( SDLK_8 )
-DEF_SDL_KEY( SDLK_9 )
-DEF_SDL_KEY( SDLK_COLON )
-DEF_SDL_KEY( SDLK_SEMICOLON )
-DEF_SDL_KEY( SDLK_LESS )
-DEF_SDL_KEY( SDLK_EQUALS )
-DEF_SDL_KEY( SDLK_GREATER )
-DEF_SDL_KEY( SDLK_QUESTION )
-DEF_SDL_KEY( SDLK_AT )
-DEF_SDL_KEY( /* )
-DEF_SDL_KEY( Skip uppercase letters )
-DEF_SDL_KEY( */ )
-DEF_SDL_KEY( SDLK_LEFTBRACKET )
-DEF_SDL_KEY( SDLK_BACKSLASH )
-DEF_SDL_KEY( SDLK_RIGHTBRACKET )
-DEF_SDL_KEY( SDLK_CARET )
-DEF_SDL_KEY( SDLK_UNDERSCORE )
-DEF_SDL_KEY( SDLK_BACKQUOTE )
-DEF_SDL_KEY( SDLK_a )
-DEF_SDL_KEY( SDLK_b )
-DEF_SDL_KEY( SDLK_c )
-DEF_SDL_KEY( SDLK_d )
-DEF_SDL_KEY( SDLK_e )
-DEF_SDL_KEY( SDLK_f )
-DEF_SDL_KEY( SDLK_g )
-DEF_SDL_KEY( SDLK_h )
-DEF_SDL_KEY( SDLK_i )
-DEF_SDL_KEY( SDLK_j )
-DEF_SDL_KEY( SDLK_k )
-DEF_SDL_KEY( SDLK_l )
-DEF_SDL_KEY( SDLK_m )
-DEF_SDL_KEY( SDLK_n )
-DEF_SDL_KEY( SDLK_o )
-DEF_SDL_KEY( SDLK_p )
-DEF_SDL_KEY( SDLK_q )
-DEF_SDL_KEY( SDLK_r )
-DEF_SDL_KEY( SDLK_s )
-DEF_SDL_KEY( SDLK_t )
-DEF_SDL_KEY( SDLK_u )
-DEF_SDL_KEY( SDLK_v )
-DEF_SDL_KEY( SDLK_w )
-DEF_SDL_KEY( SDLK_x )
-DEF_SDL_KEY( SDLK_y )
-DEF_SDL_KEY( SDLK_z )
-DEF_SDL_KEY( SDLK_DELETE )
-DEF_SDL_KEY( SDLK_WORLD_0 )
-DEF_SDL_KEY( SDLK_WORLD_1 )
-DEF_SDL_KEY( SDLK_WORLD_2 )
-DEF_SDL_KEY( SDLK_WORLD_3 )
-DEF_SDL_KEY( SDLK_WORLD_4 )
-DEF_SDL_KEY( SDLK_WORLD_5 )
-DEF_SDL_KEY( SDLK_WORLD_6 )
-DEF_SDL_KEY( SDLK_WORLD_7 )
-DEF_SDL_KEY( SDLK_WORLD_8 )
-DEF_SDL_KEY( SDLK_WORLD_9 )
-DEF_SDL_KEY( SDLK_WORLD_10 )
-DEF_SDL_KEY( SDLK_WORLD_11 )
-DEF_SDL_KEY( SDLK_WORLD_12 )
-DEF_SDL_KEY( SDLK_WORLD_13 )
-DEF_SDL_KEY( SDLK_WORLD_14 )
-DEF_SDL_KEY( SDLK_WORLD_15 )
-DEF_SDL_KEY( SDLK_WORLD_16 )
-DEF_SDL_KEY( SDLK_WORLD_17 )
-DEF_SDL_KEY( SDLK_WORLD_18 )
-DEF_SDL_KEY( SDLK_WORLD_19 )
-DEF_SDL_KEY( SDLK_WORLD_20 )
-DEF_SDL_KEY( SDLK_WORLD_21 )
-DEF_SDL_KEY( SDLK_WORLD_22 )
-DEF_SDL_KEY( SDLK_WORLD_23 )
-DEF_SDL_KEY( SDLK_WORLD_24 )
-DEF_SDL_KEY( SDLK_WORLD_25 )
-DEF_SDL_KEY( SDLK_WORLD_26 )
-DEF_SDL_KEY( SDLK_WORLD_27 )
-DEF_SDL_KEY( SDLK_WORLD_28 )
-DEF_SDL_KEY( SDLK_WORLD_29 )
-DEF_SDL_KEY( SDLK_WORLD_30 )
-DEF_SDL_KEY( SDLK_WORLD_31 )
-DEF_SDL_KEY( SDLK_WORLD_32 )
-DEF_SDL_KEY( SDLK_WORLD_33 )
-DEF_SDL_KEY( SDLK_WORLD_34 )
-DEF_SDL_KEY( SDLK_WORLD_35 )
-DEF_SDL_KEY( SDLK_WORLD_36 )
-DEF_SDL_KEY( SDLK_WORLD_37 )
-DEF_SDL_KEY( SDLK_WORLD_38 )
-DEF_SDL_KEY( SDLK_WORLD_39 )
-DEF_SDL_KEY( SDLK_WORLD_40 )
-DEF_SDL_KEY( SDLK_WORLD_41 )
-DEF_SDL_KEY( SDLK_WORLD_42 )
-DEF_SDL_KEY( SDLK_WORLD_43 )
-DEF_SDL_KEY( SDLK_WORLD_44 )
-DEF_SDL_KEY( SDLK_WORLD_45 )
-DEF_SDL_KEY( SDLK_WORLD_46 )
-DEF_SDL_KEY( SDLK_WORLD_47 )
-DEF_SDL_KEY( SDLK_WORLD_48 )
-DEF_SDL_KEY( SDLK_WORLD_49 )
-DEF_SDL_KEY( SDLK_WORLD_50 )
-DEF_SDL_KEY( SDLK_WORLD_51 )
-DEF_SDL_KEY( SDLK_WORLD_52 )
-DEF_SDL_KEY( SDLK_WORLD_53 )
-DEF_SDL_KEY( SDLK_WORLD_54 )
-DEF_SDL_KEY( SDLK_WORLD_55 )
-DEF_SDL_KEY( SDLK_WORLD_56 )
-DEF_SDL_KEY( SDLK_WORLD_57 )
-DEF_SDL_KEY( SDLK_WORLD_58 )
-DEF_SDL_KEY( SDLK_WORLD_59 )
-DEF_SDL_KEY( SDLK_WORLD_60 )
-DEF_SDL_KEY( SDLK_WORLD_61 )
-DEF_SDL_KEY( SDLK_WORLD_62 )
-DEF_SDL_KEY( SDLK_WORLD_63 )
-DEF_SDL_KEY( SDLK_WORLD_64 )
-DEF_SDL_KEY( SDLK_WORLD_65 )
-DEF_SDL_KEY( SDLK_WORLD_66 )
-DEF_SDL_KEY( SDLK_WORLD_67 )
-DEF_SDL_KEY( SDLK_WORLD_68 )
-DEF_SDL_KEY( SDLK_WORLD_69 )
-DEF_SDL_KEY( SDLK_WORLD_70 )
-DEF_SDL_KEY( SDLK_WORLD_71 )
-DEF_SDL_KEY( SDLK_WORLD_72 )
-DEF_SDL_KEY( SDLK_WORLD_73 )
-DEF_SDL_KEY( SDLK_WORLD_74 )
-DEF_SDL_KEY( SDLK_WORLD_75 )
-DEF_SDL_KEY( SDLK_WORLD_76 )
-DEF_SDL_KEY( SDLK_WORLD_77 )
-DEF_SDL_KEY( SDLK_WORLD_78 )
-DEF_SDL_KEY( SDLK_WORLD_79 )
-DEF_SDL_KEY( SDLK_WORLD_80 )
-DEF_SDL_KEY( SDLK_WORLD_81 )
-DEF_SDL_KEY( SDLK_WORLD_82 )
-DEF_SDL_KEY( SDLK_WORLD_83 )
-DEF_SDL_KEY( SDLK_WORLD_84 )
-DEF_SDL_KEY( SDLK_WORLD_85 )
-DEF_SDL_KEY( SDLK_WORLD_86 )
-DEF_SDL_KEY( SDLK_WORLD_87 )
-DEF_SDL_KEY( SDLK_WORLD_88 )
-DEF_SDL_KEY( SDLK_WORLD_89 )
-DEF_SDL_KEY( SDLK_WORLD_90 )
-DEF_SDL_KEY( SDLK_WORLD_91 )
-DEF_SDL_KEY( SDLK_WORLD_92 )
-DEF_SDL_KEY( SDLK_WORLD_93 )
-DEF_SDL_KEY( SDLK_WORLD_94 )
-DEF_SDL_KEY( SDLK_WORLD_95 )
-DEF_SDL_KEY( SDLK_KP0 )
-DEF_SDL_KEY( SDLK_KP1 )
-DEF_SDL_KEY( SDLK_KP2 )
-DEF_SDL_KEY( SDLK_KP3 )
-DEF_SDL_KEY( SDLK_KP4 )
-DEF_SDL_KEY( SDLK_KP5 )
-DEF_SDL_KEY( SDLK_KP6 )
-DEF_SDL_KEY( SDLK_KP7 )
-DEF_SDL_KEY( SDLK_KP8 )
-DEF_SDL_KEY( SDLK_KP9 )
-DEF_SDL_KEY( SDLK_KP_PERIOD )
-DEF_SDL_KEY( SDLK_KP_DIVIDE )
-DEF_SDL_KEY( SDLK_KP_MULTIPLY )
-DEF_SDL_KEY( SDLK_KP_MINUS )
-DEF_SDL_KEY( SDLK_KP_PLUS )
-DEF_SDL_KEY( SDLK_KP_ENTER )
-DEF_SDL_KEY( SDLK_KP_EQUALS )
-DEF_SDL_KEY( SDLK_UP )
-DEF_SDL_KEY( SDLK_DOWN )
-DEF_SDL_KEY( SDLK_RIGHT )
-DEF_SDL_KEY( SDLK_LEFT )
-DEF_SDL_KEY( SDLK_INSERT )
-DEF_SDL_KEY( SDLK_HOME )
-DEF_SDL_KEY( SDLK_END )
-DEF_SDL_KEY( SDLK_PAGEUP )
-DEF_SDL_KEY( SDLK_PAGEDOWN )
-DEF_SDL_KEY( SDLK_F1 )
-DEF_SDL_KEY( SDLK_F2 )
-DEF_SDL_KEY( SDLK_F3 )
-DEF_SDL_KEY( SDLK_F4 )
-DEF_SDL_KEY( SDLK_F5 )
-DEF_SDL_KEY( SDLK_F6 )
-DEF_SDL_KEY( SDLK_F7 )
-DEF_SDL_KEY( SDLK_F8 )
-DEF_SDL_KEY( SDLK_F9 )
-DEF_SDL_KEY( SDLK_F10 )
-DEF_SDL_KEY( SDLK_F11 )
-DEF_SDL_KEY( SDLK_F12 )
-DEF_SDL_KEY( SDLK_F13 )
-DEF_SDL_KEY( SDLK_F14 )
-DEF_SDL_KEY( SDLK_F15 )
-DEF_SDL_KEY( SDLK_NUMLOCK )
-DEF_SDL_KEY( SDLK_CAPSLOCK )
-DEF_SDL_KEY( SDLK_SCROLLOCK )
-DEF_SDL_KEY( SDLK_RSHIFT )
-DEF_SDL_KEY( SDLK_LSHIFT )
-DEF_SDL_KEY( SDLK_RCTRL )
-DEF_SDL_KEY( SDLK_LCTRL )
-DEF_SDL_KEY( SDLK_RALT )
-DEF_SDL_KEY( SDLK_LALT )
-DEF_SDL_KEY( SDLK_RMETA )
-DEF_SDL_KEY( SDLK_LMETA )
-DEF_SDL_KEY( SDLK_LSUPER )
-DEF_SDL_KEY( SDLK_RSUPER )
-DEF_SDL_KEY( SDLK_MODE )
-DEF_SDL_KEY( SDLK_COMPOSE )
-DEF_SDL_KEY( SDLK_HELP )
-DEF_SDL_KEY( SDLK_PRINT )
-DEF_SDL_KEY( SDLK_SYSREQ )
-DEF_SDL_KEY( SDLK_BREAK )
-DEF_SDL_KEY( SDLK_MENU )
-DEF_SDL_KEY( SDLK_POWER )
-DEF_SDL_KEY( SDLK_EURO )
-DEF_SDL_KEY( SDLK_UNDO )
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: siminterface.cc,v 1.105 2004/01/05 22:18:01 cbothamy Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// See siminterface.h for description of the siminterface concept.
-// Basically, the siminterface is visible from both the simulator and
-// the configuration user interface, and allows them to talk to each other.
-
-#include "bochs.h"
-
-bx_simulator_interface_c *SIM = NULL;
-logfunctions *siminterface_log = NULL;
-#define LOG_THIS siminterface_log->
-
-// bx_simulator_interface just defines the interface that the Bochs simulator
-// and the gui will use to talk to each other. None of the methods of
-// bx_simulator_interface are implemented; they are all virtual. The
-// bx_real_sim_c class is a child of bx_simulator_interface_c, and it
-// implements all the methods. The idea is that a gui needs to know only
-// definition of bx_simulator_interface to talk to Bochs. The gui should
-// not need to include bochs.h.
-//
-// I made this separation to ensure that all guis use the siminterface to do
-// access bochs internals, instead of accessing things like
-// bx_keyboard.s.internal_buffer[4] (or whatever) directly. -Bryce
-//
-
-class bx_real_sim_c : public bx_simulator_interface_c {
- bxevent_handler bxevent_callback;
- void *bxevent_callback_data;
- const char *registered_ci_name;
- config_interface_callback_t ci_callback;
- void *ci_callback_data;
- int init_done;
- bx_param_c **param_registry;
- int registry_alloc_size;
- int enabled;
- // save context to jump to if we must quit unexpectedly
- jmp_buf *quit_context;
- int exit_code;
-public:
- bx_real_sim_c ();
- virtual ~bx_real_sim_c ();
- virtual void set_quit_context (jmp_buf *context) { quit_context = context; }
- virtual int get_init_done () { return init_done; }
- virtual int set_init_done (int n) { init_done = n; return 0;}
- virtual void get_param_id_range (int *min, int *max) {
- *min = BXP_NULL;
- *max = BXP_THIS_IS_THE_LAST-1;
- }
- virtual int register_param (bx_id id, bx_param_c *it);
- virtual void reset_all_param ();
- virtual bx_param_c *get_param (bx_id id);
- virtual bx_param_num_c *get_param_num (bx_id id);
- virtual bx_param_string_c *get_param_string (bx_id id);
- virtual bx_param_bool_c *get_param_bool (bx_id id);
- virtual bx_param_enum_c *get_param_enum (bx_id id);
- virtual int get_n_log_modules ();
- virtual char *get_prefix (int mod);
- virtual int get_log_action (int mod, int level);
- virtual void set_log_action (int mod, int level, int action);
- virtual char *get_action_name (int action);
- virtual int get_default_log_action (int level) {
- return logfunctions::get_default_action (level);
- }
- virtual void set_default_log_action (int level, int action) {
- logfunctions::set_default_action (level, action);
- }
- virtual const char *get_log_level_name (int level);
- virtual int get_max_log_level ();
- virtual void quit_sim (int code);
- virtual int get_exit_code () { return exit_code; }
- virtual int get_default_rc (char *path, int len);
- virtual int read_rc (char *path);
- virtual int write_rc (char *path, int overwrite);
- virtual int get_log_file (char *path, int len);
- virtual int set_log_file (char *path);
- virtual int get_log_prefix (char *prefix, int len);
- virtual int set_log_prefix (char *prefix);
- virtual int get_debugger_log_file (char *path, int len);
- virtual int set_debugger_log_file (char *path);
- virtual int get_floppy_options (int drive, bx_floppy_options *out);
- virtual int get_cdrom_options (int drive, bx_atadevice_options *out, int *device = NULL);
- virtual char *get_floppy_type_name (int type);
- virtual void set_notify_callback (bxevent_handler func, void *arg);
- virtual void get_notify_callback (bxevent_handler *func, void **arg);
- virtual BxEvent* sim_to_ci_event (BxEvent *event);
- virtual int log_msg (const char *prefix, int level, const char *msg);
- virtual int ask_param (bx_id which);
- // ask the user for a pathname
- virtual int ask_filename (char *filename, int maxlen, char *prompt, char *the_default, int flags);
- // called at a regular interval, currently by the keyboard handler.
- virtual void periodic ();
- virtual int create_disk_image (const char *filename, int sectors, bx_bool overwrite);
- virtual void refresh_ci ();
- virtual void refresh_vga () {
- // maybe need to check if something has been initialized yet?
- DEV_vga_refresh();
- }
- virtual void handle_events () {
- // maybe need to check if something has been initialized yet?
- bx_gui->handle_events ();
- }
- // find first hard drive or cdrom
- bx_param_c *get_first_atadevice (Bit32u search_type);
- bx_param_c *get_first_cdrom () {
- return get_first_atadevice (BX_ATA_DEVICE_CDROM);
- }
- bx_param_c *get_first_hd () {
- return get_first_atadevice (BX_ATA_DEVICE_DISK);
- }
-#if BX_DEBUGGER
- virtual void debug_break ();
- virtual void debug_interpret_cmd (char *cmd);
- virtual char *debug_get_next_command ();
- virtual void debug_puts (const char *cmd);
-#endif
- virtual void register_configuration_interface (
- const char* name,
- config_interface_callback_t callback,
- void *userdata);
- virtual int configuration_interface(const char* name, ci_command_t command);
- virtual int begin_simulation (int argc, char *argv[]);
- virtual void set_sim_thread_func (is_sim_thread_func_t func) {}
- virtual bool is_sim_thread ();
- bool wxsel;
- virtual bool is_wx_selected () { return wxsel; }
- // provide interface to bx_gui->set_display_mode() method for config
- // interfaces to use.
- virtual void set_display_mode (disp_mode_t newmode) {
- if (bx_gui != NULL)
- bx_gui->set_display_mode (newmode);
- }
- virtual bool test_for_text_console ();
-};
-
-bx_param_c *
-bx_real_sim_c::get_param (bx_id id)
-{
- BX_ASSERT (id >= BXP_NULL && id < BXP_THIS_IS_THE_LAST);
- int index = (int)id - BXP_NULL;
- bx_param_c *retval = param_registry[index];
- if (!retval)
- BX_INFO (("get_param can't find id %u", id));
- return retval;
-}
-
-bx_param_num_c *
-bx_real_sim_c::get_param_num (bx_id id) {
- bx_param_c *generic = get_param(id);
- if (generic==NULL) {
- BX_PANIC (("get_param_num(%u) could not find a parameter", id));
- return NULL;
- }
- int type = generic->get_type ();
- if (type == BXT_PARAM_NUM || type == BXT_PARAM_BOOL || type == BXT_PARAM_ENUM)
- return (bx_param_num_c *)generic;
- BX_PANIC (("get_param_num %u could not find an integer parameter with that id", id));
- return NULL;
-}
-
-bx_param_string_c *
-bx_real_sim_c::get_param_string (bx_id id) {
- bx_param_c *generic = get_param(id);
- if (generic==NULL) {
- BX_PANIC (("get_param_string(%u) could not find a parameter", id));
- return NULL;
- }
- if (generic->get_type () == BXT_PARAM_STRING)
- return (bx_param_string_c *)generic;
- BX_PANIC (("get_param_string %u could not find an integer parameter with that id", id));
- return NULL;
-}
-
-bx_param_bool_c *
-bx_real_sim_c::get_param_bool (bx_id id) {
- bx_param_c *generic = get_param(id);
- if (generic==NULL) {
- BX_PANIC (("get_param_bool(%u) could not find a parameter", id));
- return NULL;
- }
- if (generic->get_type () == BXT_PARAM_BOOL)
- return (bx_param_bool_c *)generic;
- BX_PANIC (("get_param_bool %u could not find a bool parameter with that id", id));
- return NULL;
-}
-
-bx_param_enum_c *
-bx_real_sim_c::get_param_enum (bx_id id) {
- bx_param_c *generic = get_param(id);
- if (generic==NULL) {
- BX_PANIC (("get_param_enum(%u) could not find a parameter", id));
- return NULL;
- }
- if (generic->get_type () == BXT_PARAM_ENUM)
- return (bx_param_enum_c *)generic;
- BX_PANIC (("get_param_enum %u could not find a enum parameter with that id", id));
- return NULL;
-}
-
-void bx_init_siminterface ()
-{
- siminterface_log = new logfunctions ();
- siminterface_log->put ("CTRL");
- siminterface_log->settype(CTRLLOG);
- if (SIM == NULL)
- SIM = new bx_real_sim_c();
-}
-
-bx_simulator_interface_c::bx_simulator_interface_c ()
-{
-}
-
-bx_real_sim_c::bx_real_sim_c ()
-{
- bxevent_callback = NULL;
- bxevent_callback_data = NULL;
- ci_callback = NULL;
- ci_callback_data = NULL;
- is_sim_thread_func = NULL;
- wxsel = false;
-
- enabled = 1;
- int i;
- init_done = 0;
- registry_alloc_size = BXP_THIS_IS_THE_LAST - BXP_NULL;
- param_registry = new bx_param_c* [registry_alloc_size];
- for (i=0; i<registry_alloc_size; i++)
- param_registry[i] = NULL;
- quit_context = NULL;
- exit_code = 0;
-}
-
-// called by constructor of bx_param_c, so that every parameter that is
-// initialized gets registered. This builds a list of all parameters
-// which can be used to look them up by number (get_param).
-bx_real_sim_c::~bx_real_sim_c ()
-{
- if ( param_registry != NULL )
- {
- delete [] param_registry;
- param_registry = NULL;
- }
-}
-
-int
-bx_real_sim_c::register_param (bx_id id, bx_param_c *it)
-{
- if (id == BXP_NULL) return 0;
- BX_ASSERT (id >= BXP_NULL && id < BXP_THIS_IS_THE_LAST);
- int index = (int)id - BXP_NULL;
- if (this->param_registry[index] != NULL) {
- BX_INFO (("register_param is overwriting parameter id %d", id));
- }
- this->param_registry[index] = it;
- return 0;
-}
-
-void
-bx_real_sim_c::reset_all_param ()
-{
- bx_reset_options ();
-}
-
-int
-bx_real_sim_c::get_n_log_modules ()
-{
- return io->get_n_logfns ();
-}
-
-char *
-bx_real_sim_c::get_prefix (int mod)
-{
- logfunc_t *logfn = io->get_logfn (mod);
- return logfn->getprefix ();
-}
-
-int
-bx_real_sim_c::get_log_action (int mod, int level)
-{
- logfunc_t *logfn = io->get_logfn (mod);
- return logfn->getonoff (level);
-}
-
-void
-bx_real_sim_c::set_log_action (int mod, int level, int action)
-{
- // normal
- if (mod >= 0) {
- logfunc_t *logfn = io->get_logfn (mod);
- logfn->setonoff (level, action);
- return;
- }
- // if called with mod<0 loop over all
- int nmod = get_n_log_modules ();
- for (mod=0; mod<nmod; mod++)
- set_log_action (mod, level, action);
-}
-
-char *
-bx_real_sim_c::get_action_name (int action)
-{
- return io->getaction (action);
-}
-
-const char *
-bx_real_sim_c::get_log_level_name (int level)
-{
- return io->getlevel (level);
-}
-
-int
-bx_real_sim_c::get_max_log_level ()
-{
- return N_LOGLEV;
-}
-
-void
-bx_real_sim_c::quit_sim (int code) {
- BX_INFO (("quit_sim called with exit code %d", code));
- exit_code = code;
- // use longjmp to quit cleanly, no matter where in the stack we are.
- //fprintf (stderr, "using longjmp() to jump directly to the quit context!\n");
- if (quit_context != NULL) {
- longjmp (*quit_context, 1);
- BX_PANIC (("in bx_real_sim_c::quit_sim, longjmp should never return"));
- }
- if (SIM->is_wx_selected ()) {
- // in wxWindows, the whole simulator is running in a separate thread.
- // our only job is to end the thread as soon as possible, NOT to shut
- // down the whole application with an exit.
- BX_CPU(0)->async_event = 1;
- BX_CPU(0)->kill_bochs_request = 1;
- // the cpu loop will exit very soon after this condition is set.
- } else {
- // just a single thread. Use exit() to stop the application.
- if (!code)
- BX_PANIC (("Quit simulation command"));
- ::exit (exit_code);
- }
-}
-
-int
-bx_real_sim_c::get_default_rc (char *path, int len)
-{
- char *rc = bx_find_bochsrc ();
- if (rc == NULL) return -1;
- strncpy (path, rc, len);
- path[len-1] = 0;
- return 0;
-}
-
-int
-bx_real_sim_c::read_rc (char *rc)
-{
- return bx_read_configuration (rc);
-}
-
-// return values:
-// 0: written ok
-// -1: failed
-// -2: already exists, and overwrite was off
-int
-bx_real_sim_c::write_rc (char *rc, int overwrite)
-{
- return bx_write_configuration (rc, overwrite);
-}
-
-int
-bx_real_sim_c::get_log_file (char *path, int len)
-{
- strncpy (path, bx_options.log.Ofilename->getptr (), len);
- return 0;
-}
-
-int
-bx_real_sim_c::set_log_file (char *path)
-{
- bx_options.log.Ofilename->set (path);
- return 0;
-}
-
-int
-bx_real_sim_c::get_log_prefix (char *prefix, int len)
-{
- strncpy (prefix, bx_options.log.Oprefix->getptr (), len);
- return 0;
-}
-
-int
-bx_real_sim_c::set_log_prefix (char *prefix)
-{
- bx_options.log.Oprefix->set (prefix);
- return 0;
-}
-
-int
-bx_real_sim_c::get_debugger_log_file (char *path, int len)
-{
- strncpy (path, bx_options.log.Odebugger_filename->getptr (), len);
- return 0;
-}
-
-int
-bx_real_sim_c::set_debugger_log_file (char *path)
-{
- bx_options.log.Odebugger_filename->set (path);
- return 0;
-}
-
-int
-bx_real_sim_c::get_floppy_options (int drive, bx_floppy_options *out)
-{
- *out = (drive==0)? bx_options.floppya : bx_options.floppyb;
- return 0;
-}
-
-int
-bx_real_sim_c::get_cdrom_options (int level, bx_atadevice_options *out, int *where)
-{
- for (Bit8u channel=0; channel<BX_MAX_ATA_CHANNEL; channel++) {
- for (Bit8u device=0; device<2; device++) {
- if (bx_options.atadevice[channel][device].Otype->get() == BX_ATA_DEVICE_CDROM) {
- if (level==0) {
- *out = bx_options.atadevice[channel][device];
- if (where != NULL) *where=(channel*2)+device;
- return 1;
- }
- else level--;
- }
- }
- }
- return 0;
-}
-
-char *bochs_start_names[] = { "quick", "load", "edit", "run" };
-int n_bochs_start_names = 3;
-
-char *floppy_type_names[] = { "none", "1.2M", "1.44M", "2.88M", "720K", "360K", "160K", "180K", "320K", NULL };
-int floppy_type_n_sectors[] = { -1, 80*2*15, 80*2*18, 80*2*36, 80*2*9, 40*2*9, 40*1*8, 40*1*9, 40*2*8 };
-int n_floppy_type_names = 9;
-
-char *floppy_status_names[] = { "ejected", "inserted", NULL };
-int n_floppy_status_names = 2;
-char *floppy_bootdisk_names[] = { "floppy", "disk","cdrom", NULL };
-int n_floppy_bootdisk_names = 3;
-char *loader_os_names[] = { "none", "linux", "nullkernel", NULL };
-int n_loader_os_names = 3;
-char *keyboard_type_names[] = { "xt", "at", "mf", NULL };
-int n_keyboard_type_names = 3;
-
-char *atadevice_type_names[] = { "disk", "cdrom", NULL };
-int n_atadevice_type_names = 2;
-//char *atadevice_mode_names[] = { "flat", "concat", "external", "dll", "sparse", "vmware3", "split", "undoable", "growing", "volatile", "z-undoable", "z-volatile", NULL };
-char *atadevice_mode_names[] = { "flat", "concat", "external", "dll", "sparse", "vmware3", "undoable", "growing", "volatile", NULL };
-int n_atadevice_mode_names = 9;
-char *atadevice_status_names[] = { "ejected", "inserted", NULL };
-int n_atadevice_status_names = 2;
-char *atadevice_biosdetect_names[] = { "none", "auto", "cmos", NULL };
-int n_atadevice_biosdetect_names = 3;
-char *atadevice_translation_names[] = { "none", "lba", "large", "rechs", "auto", NULL };
-int n_atadevice_translation_names = 5;
-char *clock_sync_names[] = { "none", "realtime", "slowdown", "both", NULL };
-int clock_sync_n_names=4;
-
-
-
-char *
-bx_real_sim_c::get_floppy_type_name (int type)
-{
- BX_ASSERT (type >= BX_FLOPPY_NONE && type <= BX_FLOPPY_LAST);
- type -= BX_FLOPPY_NONE;
- return floppy_type_names[type];
-}
-
-void
-bx_real_sim_c::set_notify_callback (bxevent_handler func, void *arg)
-{
- bxevent_callback = func;
- bxevent_callback_data = arg;
-}
-
-void bx_real_sim_c::get_notify_callback (
- bxevent_handler *func,
- void **arg)
-{
- *func = bxevent_callback;
- *arg = bxevent_callback_data;
-}
-
-BxEvent *
-bx_real_sim_c::sim_to_ci_event (BxEvent *event)
-{
- if (bxevent_callback == NULL) {
- BX_ERROR (("notify called, but no bxevent_callback function is registered"));
- return NULL;
- } else {
- return (*bxevent_callback)(bxevent_callback_data, event);
- }
-}
-
-// returns 0 for continue, 1 for alwayscontinue, 2 for die.
-int
-bx_real_sim_c::log_msg (const char *prefix, int level, const char *msg)
-{
- BxEvent be;
- be.type = BX_SYNC_EVT_LOG_ASK;
- be.u.logmsg.prefix = prefix;
- be.u.logmsg.level = level;
- be.u.logmsg.msg = msg;
- // default return value in case something goes wrong.
- be.retcode = BX_LOG_ASK_CHOICE_DIE;
- //fprintf (stderr, "calling notify.\n");
- sim_to_ci_event (&be);
- return be.retcode;
-}
-
-// Called by simulator whenever it needs the user to choose a new value
-// for a registered parameter. Create a synchronous ASK_PARAM event,
-// send it to the CI, and wait for the response. The CI will call the
-// set() method on the parameter if the user changes the value.
-int
-bx_real_sim_c::ask_param (bx_id param)
-{
- bx_param_c *paramptr = SIM->get_param(param);
- BX_ASSERT (paramptr != NULL);
- // create appropriate event
- BxEvent event;
- event.type = BX_SYNC_EVT_ASK_PARAM;
- event.u.param.param = paramptr;
- sim_to_ci_event (&event);
- return event.retcode;
-}
-
-int
-bx_real_sim_c::ask_filename (char *filename, int maxlen, char *prompt, char *the_default, int flags)
-{
- // implement using ASK_PARAM on a newly created param. I can't use
- // ask_param because I don't intend to register this param.
- BxEvent event;
- bx_param_string_c param (BXP_NULL, prompt, "filename", the_default, maxlen);
- flags |= param.IS_FILENAME;
- param.get_options()->set (flags);
- event.type = BX_SYNC_EVT_ASK_PARAM;
- event.u.param.param = ¶m;
- sim_to_ci_event (&event);
- if (event.retcode >= 0)
- memcpy (filename, param.getptr(), maxlen);
- return event.retcode;
-}
-
-void
-bx_real_sim_c::periodic ()
-{
- // give the GUI a chance to do periodic things on the bochs thread. in
- // particular, notice if the thread has been asked to die.
- BxEvent tick;
- tick.type = BX_SYNC_EVT_TICK;
- sim_to_ci_event (&tick);
- if (tick.retcode < 0) {
- BX_INFO (("Bochs thread has been asked to quit."));
- bx_atexit ();
- quit_sim (0);
- }
- static int refresh_counter = 0;
- if (++refresh_counter == 50) {
- // only ask the CI to refresh every 50 times periodic() is called.
- // This should obviously be configurable because system speeds and
- // user preferences vary.
- refresh_ci ();
- refresh_counter = 0;
- }
-#if 0
- // watch for memory leaks. Allocate a small block of memory, print the
- // pointer that is returned, then free.
- BxEvent *memcheck = new BxEvent ();
- BX_INFO(("memory allocation at %p", memcheck));
- delete memcheck;
-#endif
-}
-
-// create a disk image file called filename, size=512 bytes * sectors.
-// If overwrite is true and the file exists, returns -1 without changing it.
-// Otherwise, opens up the image and starts writing. Returns -2 if
-// the image could not be opened, or -3 if there are failures during
-// write, e.g. disk full.
-//
-// wxWindows: This may be called from the gui thread.
-int
-bx_real_sim_c::create_disk_image (
- const char *filename,
- int sectors,
- bx_bool overwrite)
-{
- FILE *fp;
- if (!overwrite) {
- // check for existence first
- fp = fopen (filename, "r");
- if (fp) {
- // yes it exists
- fclose (fp);
- return -1;
- }
- }
- fp = fopen (filename, "w");
- if (fp == NULL) {
-#ifdef HAVE_PERROR
- char buffer[1024];
- sprintf (buffer, "while opening '%s' for writing", filename);
- perror (buffer);
- // not sure how to get this back into the CI
-#endif
- return -2;
- }
- int sec = sectors;
- /*
- * seek to sec*512-1 and write a single character.
- * can't just do: fseek(fp, 512*sec-1, SEEK_SET)
- * because 512*sec may be too large for signed int.
- */
- while (sec > 0)
- {
- /* temp <-- min(sec, 4194303)
- * 4194303 is (int)(0x7FFFFFFF/512)
- */
- int temp = ((sec < 4194303) ? sec : 4194303);
- fseek(fp, 512*temp, SEEK_CUR);
- sec -= temp;
- }
-
- fseek(fp, -1, SEEK_CUR);
- if (fputc('\0', fp) == EOF)
- {
- fclose (fp);
- return -3;
- }
- fclose (fp);
- return 0;
-}
-
-void bx_real_sim_c::refresh_ci () {
- if (SIM->is_wx_selected ()) {
- // presently, only wxWindows interface uses these events
- // It's an async event, so allocate a pointer and send it.
- // The event will be freed by the recipient.
- BxEvent *event = new BxEvent ();
- event->type = BX_ASYNC_EVT_REFRESH;
- sim_to_ci_event (event);
- }
-}
-
-bx_param_c *
-bx_real_sim_c::get_first_atadevice (Bit32u search_type) {
- for (int channel=0; channel<BX_MAX_ATA_CHANNEL; channel++) {
- if (!bx_options.ata[channel].Opresent->get ())
- continue;
- for (int slave=0; slave<2; slave++) {
- Bit32u present = bx_options.atadevice[channel][slave].Opresent->get ();
- Bit32u type = bx_options.atadevice[channel][slave].Otype->get ();
- if (present && (type == search_type)) {
- return bx_options.atadevice[channel][slave].Omenu;
- }
- }
- }
- return NULL;
-}
-
-#if BX_DEBUGGER
-
-// this can be safely called from either thread.
-void bx_real_sim_c::debug_break () {
- bx_debug_break ();
-}
-
-// this should only be called from the sim_thread.
-void bx_real_sim_c::debug_interpret_cmd (char *cmd) {
- if (!is_sim_thread ()) {
- fprintf (stderr, "ERROR: debug_interpret_cmd called but not from sim_thread\n");
- return;
- }
- bx_dbg_interpret_line (cmd);
-}
-
-char *bx_real_sim_c::debug_get_next_command ()
-{
- fprintf (stderr, "begin debug_get_next_command\n");
- BxEvent event;
- event.type = BX_SYNC_EVT_GET_DBG_COMMAND;
- BX_INFO (("asking for next debug command"));
- sim_to_ci_event (&event);
- BX_INFO (("received next debug command: '%s'", event.u.debugcmd.command));
- if (event.retcode >= 0)
- return event.u.debugcmd.command;
- return NULL;
-}
-
-void bx_real_sim_c::debug_puts (const char *text)
-{
- if (SIM->is_wx_selected ()) {
- // send message to the wxWindows debugger
- BxEvent *event = new BxEvent ();
- event->type = BX_ASYNC_EVT_DBG_MSG;
- event->u.logmsg.msg = text;
- sim_to_ci_event (event);
- // the event will be freed by the recipient
- } else {
- // text mode debugger: just write to console
- fputs (text, stderr);
- delete [] (char *)text;
- }
-}
-#endif
-
-void
-bx_real_sim_c::register_configuration_interface (
- const char* name,
- config_interface_callback_t callback,
- void *userdata)
-{
- ci_callback = callback;
- ci_callback_data = userdata;
- registered_ci_name = name;
-}
-
-int
-bx_real_sim_c::configuration_interface(const char *ignore, ci_command_t command)
-{
- bx_param_enum_c *ci_param = SIM->get_param_enum (BXP_SEL_CONFIG_INTERFACE);
- char *name = ci_param->get_choice (ci_param->get ());
- if (!ci_callback) {
- BX_PANIC (("no configuration interface was loaded"));
- return -1;
- }
- if (strcmp (name, registered_ci_name) != 0) {
- BX_PANIC (("siminterface does not support loading one configuration interface and then calling another"));
- return -1;
- }
- if (!strcmp (name, "wx"))
- wxsel = true;
- else
- wxsel = false;
- // enter configuration mode, just while running the configuration interface
- set_display_mode (DISP_MODE_CONFIG);
- int retval = (*ci_callback)(ci_callback_data, command);
- set_display_mode (DISP_MODE_SIM);
- return retval;
-}
-
-int
-bx_real_sim_c::begin_simulation (int argc, char *argv[])
-{
- return bx_begin_simulation (argc, argv);
-}
-
-bool bx_real_sim_c::is_sim_thread ()
-{
- if (is_sim_thread_func == NULL) return true;
- return (*is_sim_thread_func)();
-}
-
-// check if the text console exists. On some platforms, if Bochs is
-// started from the "Start Menu" or by double clicking on it on a Mac,
-// there may be nothing attached to stdin/stdout/stderr. This function
-// tests if stdin/stdout/stderr are usable and returns false if not.
-bool
-bx_real_sim_c::test_for_text_console ()
-{
-#if BX_WITH_CARBON
- // In a Carbon application, you have a text console if you run the app from
- // the command line, but if you start it from the finder you don't.
- if(!isatty(STDIN_FILENO)) return false;
-#endif
- // default: yes
- return true;
-}
-
-
-/////////////////////////////////////////////////////////////////////////
-// define methods of bx_param_* and family
-/////////////////////////////////////////////////////////////////////////
-
-bx_object_c::bx_object_c (bx_id id)
-{
- this->id = id;
- this->type = BXT_OBJECT;
-}
-
-void
-bx_object_c::set_type (bx_objtype type)
-{
- this->type = type;
-}
-
-const char* bx_param_c::default_text_format = NULL;
-
-bx_param_c::bx_param_c (bx_id id, char *name, char *description)
- : bx_object_c (id)
-{
- set_type (BXT_PARAM);
- this->name = name;
- this->description = description;
- this->text_format = default_text_format;
- this->ask_format = NULL;
- this->label = NULL;
- this->runtime_param = 0;
- this->enabled = 1;
- SIM->register_param (id, this);
-}
-
-const char* bx_param_c::set_default_format (const char *f) {
- const char *old = default_text_format;
- default_text_format = f;
- return old;
-}
-
-bx_param_num_c::bx_param_num_c (bx_id id,
- char *name,
- char *description,
- Bit64s min, Bit64s max, Bit64s initial_val)
- : bx_param_c (id, name, description)
-{
- set_type (BXT_PARAM_NUM);
- this->min = min;
- this->max = max;
- this->initial_val = initial_val;
- this->val.number = initial_val;
- this->handler = NULL;
- this->enable_handler = NULL;
- this->base = default_base;
- // dependent_list must be initialized before the set(),
- // because set calls update_dependents().
- dependent_list = NULL;
- set (initial_val);
-}
-
-Bit32u bx_param_num_c::default_base = 10;
-
-Bit32u bx_param_num_c::set_default_base (Bit32u val) {
- Bit32u old = default_base;
- default_base = val;
- return old;
-}
-
-void
-bx_param_num_c::reset ()
-{
- this->val.number = initial_val;
-}
-
-void
-bx_param_num_c::set_handler (param_event_handler handler)
-{
- this->handler = handler;
- // now that there's a handler, call set once to run the handler immediately
- //set (get ());
-}
-
-void
-bx_param_num_c::set_enable_handler (param_enable_handler handler)
-{
- this->enable_handler = handler;
-}
-
-void bx_param_num_c::set_dependent_list (bx_list_c *l) {
- dependent_list = l;
- update_dependents ();
-}
-
-Bit64s
-bx_param_num_c::get64 ()
-{
- if (handler) {
- // the handler can decide what value to return and/or do some side effect
- return (*handler)(this, 0, val.number);
- } else {
- // just return the value
- return val.number;
- }
-}
-
-void
-bx_param_num_c::set (Bit64s newval)
-{
- if (handler) {
- // the handler can override the new value and/or perform some side effect
- val.number = newval;
- (*handler)(this, 1, newval);
- } else {
- // just set the value. This code does not check max/min.
- val.number = newval;
- }
- if ((val.number < min || val.number > max) && (Bit64u)max != BX_MAX_BIT64U)
- BX_PANIC (("numerical parameter %s was set to " FMT_LL "d, which is out of range " FMT_LL "d to " FMT_LL "d", get_name (), val.number, min, max));
- if (dependent_list != NULL) update_dependents ();
-}
-
-void bx_param_num_c::set_range (Bit64u min, Bit64u max)
-{
- this->min = min;
- this->max = max;
-}
-
-void bx_param_num_c::set_initial_val (Bit64s initial_val) {
- this->val.number = this->initial_val = initial_val;
-}
-
-void bx_param_num_c::update_dependents ()
-{
- if (dependent_list) {
- int en = val.number && enabled;
- for (int i=0; i<dependent_list->get_size (); i++) {
- bx_param_c *param = dependent_list->get (i);
- if (param != this)
- param->set_enabled (en);
- }
- }
-}
-
-void
-bx_param_num_c::set_enabled (int en)
-{
- // The enable handler may wish to allow/disallow the action
- if (enable_handler) {
- en = (*enable_handler) (this, en);
- }
- bx_param_c::set_enabled (en);
- update_dependents ();
-}
-
-// Signed 64 bit
-bx_shadow_num_c::bx_shadow_num_c (bx_id id,
- char *name,
- char *description,
- Bit64s *ptr_to_real_val,
- Bit8u highbit,
- Bit8u lowbit)
-: bx_param_num_c (id, name, description, BX_MIN_BIT64S, BX_MAX_BIT64S, *ptr_to_real_val)
-{
- this->varsize = 16;
- this->lowbit = lowbit;
- this->mask = (1 << (highbit - lowbit)) - 1;
- val.p64bit = ptr_to_real_val;
-}
-
-// Unsigned 64 bit
-bx_shadow_num_c::bx_shadow_num_c (bx_id id,
- char *name,
- char *description,
- Bit64u *ptr_to_real_val,
- Bit8u highbit,
- Bit8u lowbit)
-: bx_param_num_c (id, name, description, BX_MIN_BIT64U, BX_MAX_BIT64U, *ptr_to_real_val)
-{
- this->varsize = 16;
- this->lowbit = lowbit;
- this->mask = (1 << (highbit - lowbit)) - 1;
- val.p64bit = (Bit64s*) ptr_to_real_val;
-}
-
-// Signed 32 bit
-bx_shadow_num_c::bx_shadow_num_c (bx_id id,
- char *name,
- char *description,
- Bit32s *ptr_to_real_val,
- Bit8u highbit,
- Bit8u lowbit)
-: bx_param_num_c (id, name, description, BX_MIN_BIT32S, BX_MAX_BIT32S, *ptr_to_real_val)
-{
- this->varsize = 16;
- this->lowbit = lowbit;
- this->mask = (1 << (highbit - lowbit)) - 1;
- val.p32bit = ptr_to_real_val;
-}
-
-// Unsigned 32 bit
-bx_shadow_num_c::bx_shadow_num_c (bx_id id,
- char *name,
- char *description,
- Bit32u *ptr_to_real_val,
- Bit8u highbit,
- Bit8u lowbit)
-: bx_param_num_c (id, name, description, BX_MIN_BIT32U, BX_MAX_BIT32U, *ptr_to_real_val)
-{
- this->varsize = 32;
- this->lowbit = lowbit;
- this->mask = (1 << (highbit - lowbit)) - 1;
- val.p32bit = (Bit32s*) ptr_to_real_val;
-}
-
-// Signed 16 bit
-bx_shadow_num_c::bx_shadow_num_c (bx_id id,
- char *name,
- char *description,
- Bit16s *ptr_to_real_val,
- Bit8u highbit,
- Bit8u lowbit)
-: bx_param_num_c (id, name, description, BX_MIN_BIT16S, BX_MAX_BIT16S, *ptr_to_real_val)
-{
- this->varsize = 16;
- this->lowbit = lowbit;
- this->mask = (1 << (highbit - lowbit)) - 1;
- val.p16bit = ptr_to_real_val;
-}
-
-// Unsigned 16 bit
-bx_shadow_num_c::bx_shadow_num_c (bx_id id,
- char *name,
- char *description,
- Bit16u *ptr_to_real_val,
- Bit8u highbit,
- Bit8u lowbit)
-: bx_param_num_c (id, name, description, BX_MIN_BIT16U, BX_MAX_BIT16U, *ptr_to_real_val)
-{
- this->varsize = 16;
- this->lowbit = lowbit;
- this->mask = (1 << (highbit - lowbit)) - 1;
- val.p16bit = (Bit16s*) ptr_to_real_val;
-}
-
-// Signed 8 bit
-bx_shadow_num_c::bx_shadow_num_c (bx_id id,
- char *name,
- char *description,
- Bit8s *ptr_to_real_val,
- Bit8u highbit,
- Bit8u lowbit)
-: bx_param_num_c (id, name, description, BX_MIN_BIT8S, BX_MAX_BIT8S, *ptr_to_real_val)
-{
- this->varsize = 16;
- this->lowbit = lowbit;
- this->mask = (1 << (highbit - lowbit)) - 1;
- val.p8bit = ptr_to_real_val;
-}
-
-// Unsigned 8 bit
-bx_shadow_num_c::bx_shadow_num_c (bx_id id,
- char *name,
- char *description,
- Bit8u *ptr_to_real_val,
- Bit8u highbit,
- Bit8u lowbit)
-: bx_param_num_c (id, name, description, BX_MIN_BIT8U, BX_MAX_BIT8U, *ptr_to_real_val)
-{
- this->varsize = 8;
- this->lowbit = lowbit;
- this->mask = (1 << (highbit - lowbit)) - 1;
- val.p8bit = (Bit8s*) ptr_to_real_val;
-}
-
-Bit64s
-bx_shadow_num_c::get64 () {
- Bit64u current = 0;
- switch (varsize) {
- case 8: current = *(val.p8bit); break;
- case 16: current = *(val.p16bit); break;
- case 32: current = *(val.p32bit); break;
- case 64: current = *(val.p64bit); break;
- default: BX_PANIC(("unsupported varsize %d", varsize));
- }
- current = (current >> lowbit) & mask;
- if (handler) {
- // the handler can decide what value to return and/or do some side effect
- return (*handler)(this, 0, current) & mask;
- } else {
- // just return the value
- return current;
- }
-}
-
-void
-bx_shadow_num_c::set (Bit64s newval)
-{
- Bit64u tmp = 0;
- if ((newval < min || newval > max) && (Bit64u)max != BX_MAX_BIT64U)
- BX_PANIC (("numerical parameter %s was set to " FMT_LL "d, which is out of range " FMT_LL "d to " FMT_LL "d", get_name (), newval, min, max));
- switch (varsize) {
- case 8:
- tmp = (*(val.p8bit) >> lowbit) & mask;
- tmp |= (newval & mask) << lowbit;
- *(val.p8bit) = (Bit8s)tmp;
- break;
- case 16:
- tmp = (*(val.p16bit) >> lowbit) & mask;
- tmp |= (newval & mask) << lowbit;
- *(val.p16bit) = (Bit16s)tmp;
- break;
- case 32:
- tmp = (*(val.p32bit) >> lowbit) & mask;
- tmp |= (newval & mask) << lowbit;
- *(val.p32bit) = (Bit32s)tmp;
- break;
- case 64:
- tmp = (*(val.p64bit) >> lowbit) & mask;
- tmp |= (newval & mask) << lowbit;
- *(val.p64bit) = tmp;
- break;
- default:
- BX_PANIC(("unsupported varsize %d", varsize));
- }
- if (handler) {
- // the handler can override the new value and/or perform some side effect
- (*handler)(this, 1, tmp);
- }
-}
-
-bx_param_bool_c::bx_param_bool_c (bx_id id,
- char *name,
- char *description,
- Bit64s initial_val)
- : bx_param_num_c (id, name, description, 0, 1, initial_val)
-{
- set_type (BXT_PARAM_BOOL);
- set (initial_val);
-}
-
-bx_shadow_bool_c::bx_shadow_bool_c (bx_id id,
- char *name,
- char *description,
- bx_bool *ptr_to_real_val,
- Bit8u bitnum)
- : bx_param_bool_c (id, name, description, (Bit64s) *ptr_to_real_val)
-{
- val.pbool = ptr_to_real_val;
- this->bitnum = bitnum;
-}
-
-Bit64s
-bx_shadow_bool_c::get64 () {
- if (handler) {
- // the handler can decide what value to return and/or do some side effect
- Bit64s ret = (*handler)(this, 0, (Bit64s) *(val.pbool));
- return (ret>>bitnum) & 1;
- } else {
- // just return the value
- return (*(val.pbool)) & 1;
- }
-}
-
-void
-bx_shadow_bool_c::set (Bit64s newval)
-{
- // only change the bitnum bit
- Bit64s tmp = (newval&1) << bitnum;
- *(val.pbool) &= ~tmp;
- *(val.pbool) |= tmp;
- if (handler) {
- // the handler can override the new value and/or perform some side effect
- (*handler)(this, 1, newval&1);
- }
-}
-
-bx_param_enum_c::bx_param_enum_c (bx_id id,
- char *name,
- char *description,
- char **choices,
- Bit64s initial_val,
- Bit64s value_base)
- : bx_param_num_c (id, name, description, value_base, BX_MAX_BIT64S, initial_val)
-{
- set_type (BXT_PARAM_ENUM);
- this->choices = choices;
- // count number of choices, set max
- char **p = choices;
- while (*p != NULL) p++;
- this->min = value_base;
- // now that the max is known, replace the BX_MAX_BIT64S sent to the parent
- // class constructor with the real max.
- this->max = value_base + (p - choices - 1);
- set (initial_val);
-}
-
-int
-bx_param_enum_c::find_by_name (const char *string)
-{
- char **p;
- for (p=&choices[0]; *p; p++) {
- if (!strcmp (string, *p))
- return p-choices;
- }
- return -1;
-}
-
-bool
-bx_param_enum_c::set_by_name (const char *string)
-{
- int n = find_by_name (string);
- if (n<0) return false;
- set (n);
- return true;
-}
-
-bx_param_string_c::bx_param_string_c (bx_id id,
- char *name,
- char *description,
- char *initial_val,
- int maxsize)
- : bx_param_c (id, name, description)
-{
- set_type (BXT_PARAM_STRING);
- if (maxsize < 0)
- maxsize = strlen(initial_val) + 1;
- this->val = new char[maxsize];
- this->initial_val = new char[maxsize];
- this->handler = NULL;
- this->enable_handler = NULL;
- this->maxsize = maxsize;
- strncpy (this->val, initial_val, maxsize);
- strncpy (this->initial_val, initial_val, maxsize);
- this->options = new bx_param_num_c (BXP_NULL,
- "stringoptions", NULL, 0, BX_MAX_BIT64S, 0);
- set (initial_val);
-}
-
-bx_param_filename_c::bx_param_filename_c (bx_id id,
- char *name,
- char *description,
- char *initial_val,
- int maxsize)
- : bx_param_string_c (id, name, description, initial_val, maxsize)
-{
- get_options()->set (IS_FILENAME);
-}
-
-bx_param_string_c::~bx_param_string_c ()
-{
- if ( this->val != NULL )
- {
- delete [] this->val;
- this->val = NULL;
- }
- if ( this->initial_val != NULL )
- {
- delete [] this->initial_val;
- this->initial_val = NULL;
- }
-
- if ( this->options != NULL )
- {
- delete [] this->options;
- this->options = NULL;
- }
-}
-
-void
-bx_param_string_c::reset () {
- strncpy (this->val, this->initial_val, maxsize);
-}
-
-void
-bx_param_string_c::set_handler (param_string_event_handler handler)
-{
- this->handler = handler;
- // now that there's a handler, call set once to run the handler immediately
- //set (getptr ());
-}
-
-void
-bx_param_string_c::set_enable_handler (param_enable_handler handler)
-{
- this->enable_handler = handler;
-}
-
-void
-bx_param_string_c::set_enabled (int en)
-{
- // The enable handler may wish to allow/disallow the action
- if (enable_handler) {
- en = (*enable_handler) (this, en);
- }
- bx_param_c::set_enabled (en);
-}
-
-Bit32s
-bx_param_string_c::get (char *buf, int len)
-{
- if (options->get () & RAW_BYTES)
- memcpy (buf, val, len);
- else
- strncpy (buf, val, len);
- if (handler) {
- // the handler can choose to replace the value in val/len. Also its
- // return value is passed back as the return value of get.
- (*handler)(this, 0, buf, len);
- }
- return 0;
-}
-
-void
-bx_param_string_c::set (char *buf)
-{
- if (options->get () & RAW_BYTES)
- memcpy (val, buf, maxsize);
- else
- strncpy (val, buf, maxsize);
- if (handler) {
- // the handler can return a different char* to be copied into the value
- buf = (*handler)(this, 1, buf, -1);
- }
-}
-
-bx_bool
-bx_param_string_c::equals (const char *buf)
-{
- if (options->get () & RAW_BYTES)
- return (memcmp (val, buf, maxsize) == 0);
- else
- return (strncmp (val, buf, maxsize) == 0);
-}
-
-bx_list_c::bx_list_c (bx_id id, int maxsize)
- : bx_param_c (id, "list", "")
-{
- set_type (BXT_LIST);
- this->size = 0;
- this->maxsize = maxsize;
- this->list = new bx_param_c* [maxsize];
- init ();
-}
-
-bx_list_c::bx_list_c (bx_id id, char *name, char *description, int maxsize)
- : bx_param_c (id, name, description)
-{
- set_type (BXT_LIST);
- this->size = 0;
- this->maxsize = maxsize;
- this->list = new bx_param_c* [maxsize];
- init ();
-}
-
-bx_list_c::bx_list_c (bx_id id, char *name, char *description, bx_param_c **init_list)
- : bx_param_c (id, name, description)
-{
- set_type (BXT_LIST);
- this->size = 0;
- while (init_list[this->size] != NULL)
- this->size++;
- this->maxsize = this->size;
- this->list = new bx_param_c* [maxsize];
- for (int i=0; i<this->size; i++)
- this->list[i] = init_list[i];
- init ();
-}
-
-bx_list_c::~bx_list_c()
-{
- if (this->list)
- {
- delete [] this->list;
- this->list = NULL;
- }
- if ( this->title != NULL)
- {
- delete this->title;
- this->title = NULL;
- }
- if (this->options != NULL)
- {
- delete this->options;
- this->options = NULL;
- }
- if ( this->choice != NULL )
- {
- delete this->choice;
- this->choice = NULL;
- }
-}
-
-void
-bx_list_c::init ()
-{
- // the title defaults to the name
- this->title = new bx_param_string_c (BXP_NULL,
- "title of list",
- "",
- get_name (), 80);
- this->options = new bx_param_num_c (BXP_NULL,
- "list_option", "", 0, BX_MAX_BIT64S,
- 0);
- this->choice = new bx_param_num_c (BXP_NULL,
- "list_choice", "", 0, BX_MAX_BIT64S,
- 1);
- this->parent = NULL;
-}
-
-bx_list_c *
-bx_list_c::clone ()
-{
- bx_list_c *newlist = new bx_list_c (BXP_NULL, name, description, maxsize);
- for (int i=0; i<get_size (); i++)
- newlist->add (get(i));
- newlist->set_options (get_options ());
- newlist->set_parent (get_parent ());
- return newlist;
-}
-
-void
-bx_list_c::add (bx_param_c *param)
-{
- if (this->size >= this->maxsize)
- BX_PANIC (("add param %u to bx_list_c id=%u: list capacity exceeded", param->get_id (), get_id ()));
- list[size] = param;
- size++;
-}
-
-bx_param_c *
-bx_list_c::get (int index)
-{
- BX_ASSERT (index >= 0 && index < size);
- return list[index];
-}
-
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: siminterface.h,v 1.113.2.2 2004/02/06 22:14:35 danielg4 Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Before I can describe what this file is for, I have to make the
-// distinction between a configuration interface (CI) and the VGA display
-// window (VGAW). I will try to avoid the term 'GUI' because it is unclear
-// if that means CI or VGAW, and because not all interfaces are graphical
-// anyway.
-//
-// The traditional Bochs screen is a window with a large VGA display panel and
-// a series of buttons (floppy, cdrom, snapshot, power). Over the years, we
-// have collected many implementations of the VGAW for different environments
-// and platforms; each implementation is in a separate file under gui/*:
-// x.cc, win32.cc, beos.cc, macintosh.cc, etc. The files gui.h and gui.cc
-// define the platform independent part of the VGAW, leaving about 15 methods
-// of the bx_gui_c class undefined. The platform dependent file must
-// implement the remaining 15 methods.
-//
-// The configuration interface is relatively new, started by Bryce Denney in
-// June 2001. The CI is intended to allow the user to edit a variety of
-// configuration and runtime options. Some options, such as memory size or
-// enabling the ethernet card, should only be changed before the simulation
-// begins; others, such as floppy disk image, instructions per second, and
-// logging options can be safely changed at runtime. The CI allows the user to
-// make these changes. Before the CI existed, only a few things could be
-// changed at runtime, all linked to clicking on the VGAW buttons.
-//
-// At the time that the CI was conceived, we were still debating what form the
-// user interface part would take: stdin/stdout menus, a graphical application
-// with menus and dialogs running in a separate thread, or even a tiny web
-// server that you can connect to with a web browser. As a result the
-// interface to the CI was designed so that the user interface of the CI
-// could be replaced easily at compile time, or maybe even at runtime via
-// a plugin architecture. To this end, we kept a clear separation between
-// the user interface code and the siminterface, the code that interfaces with
-// the simulator. The same siminterface is used all the time, while
-// different implementations of the CI can be switched in reasonably easily.
-// Only the CI code uses library specific graphics and I/O functions; the
-// siminterface deals in portable abstractions and callback functions.
-// The first CI implementation was a series of text mode menus implemented in
-// control.cc.
-//
-// The configuration interface MUST use the siminterface methods to access the
-// simulator. It should not modify settings in some device with code like
-// bx_floppy.s.media[2].heads = 17. If such access is needed, then a
-// siminterface method should be written to make the change on the CI's behalf.
-// This separation is enforced by the fact that the CI does not even include
-// bochs.h. You'll notice that control.cc include osdep.h, control.h, and
-// siminterface.h, so it doesn't know what bx_floppy or bx_cpu_c are. I'm sure
-// some people will say is overly restrictive and/or annoying. When I set it
-// up this way, we were still talking about making the CI in a seperate
-// process, where direct method calls would be impossible. Also, we have been
-// considering turning devices into plugin modules which are dynamically
-// linked. Any direct references to something like bx_floppy.s.media[2].heads
-// would have to be reworked before a plugin interface was possible as well.
-//
-// The siminterface is the glue between the CI and the simulator. There is
-// just one global instance of the siminterface object, which can be referred
-// to by the global variable bx_simulator_interface_c *SIM; The base class
-// bx_simulator_interface_c, contains only virtual functions and it defines the
-// interface that the CI is allowed to use. In siminterface.cc, a class
-// called bx_real_sim_c is defined with bx_simulator_interface_c as its parent
-// class. Bx_real_sim_c implements each of the functions. The separation into
-// parent class and child class leaves the possibility of making a different
-// child class that talks to the simulator in a different way (networking for
-// example). If you were writing a user interface in a separate process, you
-// could define a subclass of bx_simulator_interface_c called
-// bx_siminterface_proxy_c which opens up a network port and turns all method
-// calls into network sends and receives. Because the interface is defined
-// entirely by the base class, the code that calls the methods would not know
-// the difference.
-//
-// An important part of the siminterface implementation is the use of parameter
-// classes, or bx_param_*. The parameter classes are described below, where
-// they are declared. Search for "parameter classes" below for detals.
-//
-// Also this header file declares data structures for certain events that pass
-// between the siminterface and the CI. Search for "event structures" below.
-
-
-
-//////////////////////////////////////////////////////
-// BX_UI_TEXT should be set to 1 when the text mode configuration interface
-// is compiled in. This gives each type of parameter a text_print and text_ask
-// method (defined in gui/control.cc) so that you can call text_ask() on any
-// kind of parameter to ask the user to edit the value.
-//
-// I have been considering whether to use the same strategy for the
-// wxWindows interface, but I'm not sure if I like it. One problem is
-// that in order to declare member functions that are useful for
-// wxWindows, the wxWindows header files would have to be included
-// before the param object definitions. That means that all the
-// wxwindows headers would have be included when compiling every
-// single bochs file. One of the things I like about the separation
-// between the simulator and CI is that the two parts can be
-// compiled without any knowledge of the other. Bochs doesn't include
-// <wx.h>, and the wxwindows CI (wxmain.cc) doesn't need to include <bochs.h>.
-// Aside from making compiles faster, this enforces the use of the siminterface
-// so it keeps the interface clean (important when we may have multiple UI
-// implementations for example). This argues for keeping UI-specific
-// structures out of the simulator interface. It certainly works ok for the
-// text interface, but that's because FILE* is standard and portable.
-#define BX_UI_TEXT 1
-
-//////////////////////////////////////////////////////
-
-// list of possible types for bx_param_c and descendant objects
-typedef enum {
- BXT_OBJECT = 201,
- BXT_PARAM,
- BXT_PARAM_NUM,
- BXT_PARAM_BOOL,
- BXT_PARAM_ENUM,
- BXT_PARAM_STRING,
- BXT_LIST
-} bx_objtype;
-
-// list if parameter id values. The actual values are not important;
-// it's only important that they all be different from each other.
-typedef enum {
- BXP_NULL = 301,
- BXP_IPS,
- BXP_REALTIME_PIT,
- BXP_TEXT_SNAPSHOT_CHECK,
- BXP_VGA_UPDATE_INTERVAL,
- BXP_MOUSE_ENABLED,
- BXP_MEM_SIZE,
- BXP_ROM_PATH,
- BXP_ROM_ADDRESS,
- BXP_VGA_ROM_PATH,
- BXP_OPTROM1_PATH,
- BXP_OPTROM2_PATH,
- BXP_OPTROM3_PATH,
- BXP_OPTROM4_PATH,
- BXP_OPTROM1_ADDRESS,
- BXP_OPTROM2_ADDRESS,
- BXP_OPTROM3_ADDRESS,
- BXP_OPTROM4_ADDRESS,
- BXP_KBD_SERIAL_DELAY,
- BXP_KBD_PASTE_DELAY,
- BXP_KBD_TYPE,
- BXP_FLOPPY_CMD_DELAY,
- BXP_FLOPPYA_DEVTYPE,
- BXP_FLOPPYA_PATH,
- BXP_FLOPPYA_TYPE,
- BXP_FLOPPYA_STATUS,
- BXP_FLOPPYA,
- BXP_FLOPPYB_DEVTYPE,
- BXP_FLOPPYB_PATH,
- BXP_FLOPPYB_TYPE,
- BXP_FLOPPYB_STATUS,
- BXP_FLOPPYB,
-
- BXP_ATA0_MENU,
- BXP_ATA1_MENU,
- BXP_ATA2_MENU,
- BXP_ATA3_MENU,
-#define BXP_ATAx_MENU(i) (BXP_ATA0_MENU + (i))
- BXP_ATA0,
- BXP_ATA1,
- BXP_ATA2,
- BXP_ATA3,
-#define BXP_ATAx(i) (BXP_ATA0 + (i))
- BXP_ATA0_PRESENT,
- BXP_ATA1_PRESENT,
- BXP_ATA2_PRESENT,
- BXP_ATA3_PRESENT,
-#define BXP_ATAx_PRESENT(i) (BXP_ATA0_PRESENT + (i))
- BXP_ATA0_IOADDR1,
- BXP_ATA1_IOADDR1,
- BXP_ATA2_IOADDR1,
- BXP_ATA3_IOADDR1,
-#define BXP_ATAx_IOADDR1(i) (BXP_ATA0_IOADDR1 + (i))
- BXP_ATA0_IOADDR2,
- BXP_ATA1_IOADDR2,
- BXP_ATA2_IOADDR2,
- BXP_ATA3_IOADDR2,
-#define BXP_ATAx_IOADDR2(i) (BXP_ATA0_IOADDR2 + (i))
- BXP_ATA0_IRQ,
- BXP_ATA1_IRQ,
- BXP_ATA2_IRQ,
- BXP_ATA3_IRQ,
-#define BXP_ATAx_IRQ(i) (BXP_ATA0_IRQ + (i))
-
- BXP_ATA0_MASTER,
- BXP_ATA0_SLAVE,
- BXP_ATA1_MASTER,
- BXP_ATA1_SLAVE,
- BXP_ATA2_MASTER,
- BXP_ATA2_SLAVE,
- BXP_ATA3_MASTER,
- BXP_ATA3_SLAVE,
-#define BXP_ATAx_DEVICE(i, s) (BXP_ATA0_MASTER + (2*(i)) + (s))
-
-#define BXP_PARAMS_PER_ATA_DEVICE 12
-
- BXP_ATA0_MASTER_PRESENT,
- BXP_ATA0_SLAVE_PRESENT,
- BXP_ATA1_MASTER_PRESENT,
- BXP_ATA1_SLAVE_PRESENT,
- BXP_ATA2_MASTER_PRESENT,
- BXP_ATA2_SLAVE_PRESENT,
- BXP_ATA3_MASTER_PRESENT,
- BXP_ATA3_SLAVE_PRESENT,
-#define BXP_ATAx_DEVICE_PRESENT(i, s) (BXP_ATA0_MASTER_PRESENT + (2*(i)) + (s))
-
- BXP_ATA0_MASTER_TYPE,
- BXP_ATA0_SLAVE_TYPE,
- BXP_ATA1_MASTER_TYPE,
- BXP_ATA1_SLAVE_TYPE,
- BXP_ATA2_MASTER_TYPE,
- BXP_ATA2_SLAVE_TYPE,
- BXP_ATA3_MASTER_TYPE,
- BXP_ATA3_SLAVE_TYPE,
-#define BXP_ATAx_DEVICE_TYPE(i, s) (BXP_ATA0_MASTER_TYPE + (2*(i)) + (s))
-
- BXP_ATA0_MASTER_MODE,
- BXP_ATA0_SLAVE_MODE,
- BXP_ATA1_MASTER_MODE,
- BXP_ATA1_SLAVE_MODE,
- BXP_ATA2_MASTER_MODE,
- BXP_ATA2_SLAVE_MODE,
- BXP_ATA3_MASTER_MODE,
- BXP_ATA3_SLAVE_MODE,
-#define BXP_ATAx_DEVICE_MODE(i, s) (BXP_ATA0_MASTER_MODE + (2*(i)) + (s))
-
- BXP_ATA0_MASTER_PATH,
- BXP_ATA0_SLAVE_PATH,
- BXP_ATA1_MASTER_PATH,
- BXP_ATA1_SLAVE_PATH,
- BXP_ATA2_MASTER_PATH,
- BXP_ATA2_SLAVE_PATH,
- BXP_ATA3_MASTER_PATH,
- BXP_ATA3_SLAVE_PATH,
-#define BXP_ATAx_DEVICE_PATH(i, s) (BXP_ATA0_MASTER_PATH + (2*(i)) + (s))
-
- BXP_ATA0_MASTER_CYLINDERS,
- BXP_ATA0_SLAVE_CYLINDERS,
- BXP_ATA1_MASTER_CYLINDERS,
- BXP_ATA1_SLAVE_CYLINDERS,
- BXP_ATA2_MASTER_CYLINDERS,
- BXP_ATA2_SLAVE_CYLINDERS,
- BXP_ATA3_MASTER_CYLINDERS,
- BXP_ATA3_SLAVE_CYLINDERS,
-#define BXP_ATAx_DEVICE_CYLINDERS(i, s) (BXP_ATA0_MASTER_CYLINDERS + (2*(i)) + (s))
-
- BXP_ATA0_MASTER_HEADS,
- BXP_ATA0_SLAVE_HEADS,
- BXP_ATA1_MASTER_HEADS,
- BXP_ATA1_SLAVE_HEADS,
- BXP_ATA2_MASTER_HEADS,
- BXP_ATA2_SLAVE_HEADS,
- BXP_ATA3_MASTER_HEADS,
- BXP_ATA3_SLAVE_HEADS,
-#define BXP_ATAx_DEVICE_HEADS(i, s) (BXP_ATA0_MASTER_HEADS + (2*(i)) + (s))
-
- BXP_ATA0_MASTER_SPT,
- BXP_ATA0_SLAVE_SPT,
- BXP_ATA1_MASTER_SPT,
- BXP_ATA1_SLAVE_SPT,
- BXP_ATA2_MASTER_SPT,
- BXP_ATA2_SLAVE_SPT,
- BXP_ATA3_MASTER_SPT,
- BXP_ATA3_SLAVE_SPT,
-#define BXP_ATAx_DEVICE_SPT(i, s) (BXP_ATA0_MASTER_SPT + (2*(i)) + (s))
-
- BXP_ATA0_MASTER_STATUS,
- BXP_ATA0_SLAVE_STATUS,
- BXP_ATA1_MASTER_STATUS,
- BXP_ATA1_SLAVE_STATUS,
- BXP_ATA2_MASTER_STATUS,
- BXP_ATA2_SLAVE_STATUS,
- BXP_ATA3_MASTER_STATUS,
- BXP_ATA3_SLAVE_STATUS,
-#define BXP_ATAx_DEVICE_STATUS(i, s) (BXP_ATA0_MASTER_STATUS + (2*(i)) + (s))
-
- BXP_ATA0_MASTER_MODEL,
- BXP_ATA0_SLAVE_MODEL,
- BXP_ATA1_MASTER_MODEL,
- BXP_ATA1_SLAVE_MODEL,
- BXP_ATA2_MASTER_MODEL,
- BXP_ATA2_SLAVE_MODEL,
- BXP_ATA3_MASTER_MODEL,
- BXP_ATA3_SLAVE_MODEL,
-#define BXP_ATAx_DEVICE_MODEL(i, s) (BXP_ATA0_MASTER_MODEL + (2*(i)) + (s))
-
- BXP_ATA0_MASTER_BIOSDETECT,
- BXP_ATA0_SLAVE_BIOSDETECT,
- BXP_ATA1_MASTER_BIOSDETECT,
- BXP_ATA1_SLAVE_BIOSDETECT,
- BXP_ATA2_MASTER_BIOSDETECT,
- BXP_ATA2_SLAVE_BIOSDETECT,
- BXP_ATA3_MASTER_BIOSDETECT,
- BXP_ATA3_SLAVE_BIOSDETECT,
-#define BXP_ATAx_DEVICE_BIOSDETECT(i, s) (BXP_ATA0_MASTER_BIOSDETECT + (2*(i)) + (s))
-
- BXP_ATA0_MASTER_TRANSLATION,
- BXP_ATA0_SLAVE_TRANSLATION,
- BXP_ATA1_MASTER_TRANSLATION,
- BXP_ATA1_SLAVE_TRANSLATION,
- BXP_ATA2_MASTER_TRANSLATION,
- BXP_ATA2_SLAVE_TRANSLATION,
- BXP_ATA3_MASTER_TRANSLATION,
- BXP_ATA3_SLAVE_TRANSLATION,
-#define BXP_ATAx_DEVICE_TRANSLATION(i, s) (BXP_ATA0_MASTER_TRANSLATION + (2*(i)) + (s))
-
- BXP_ATA0_MASTER_JOURNAL,
- BXP_ATA0_SLAVE_JOURNAL,
- BXP_ATA1_MASTER_JOURNAL,
- BXP_ATA1_SLAVE_JOURNAL,
- BXP_ATA2_MASTER_JOURNAL,
- BXP_ATA2_SLAVE_JOURNAL,
- BXP_ATA3_MASTER_JOURNAL,
- BXP_ATA3_SLAVE_JOURNAL,
-#define BXP_ATAx_DEVICE_JOURNAL(i, s) (BXP_ATA0_MASTER_JOURNAL + (2*(i)) + (s))
-
-#define BXP_PARAMS_PER_SERIAL_PORT 2
- BXP_COM1_ENABLED,
- BXP_COM1_PATH,
- BXP_COM2_ENABLED,
- BXP_COM2_PATH,
- BXP_COM3_ENABLED,
- BXP_COM3_PATH,
- BXP_COM4_ENABLED,
- BXP_COM4_PATH,
-#define BXP_PARAMS_PER_USB_HUB 3
- BXP_USB1_ENABLED,
- BXP_USB1_IOADDR,
- BXP_USB1_IRQ,
- BXP_PRIVATE_COLORMAP,
- BXP_FULLSCREEN,
- BXP_SCREENMODE,
- BXP_I440FX_SUPPORT,
- BXP_NEWHARDDRIVESUPPORT,
- BXP_LOG_FILENAME,
- BXP_LOG_PREFIX,
- BXP_DEBUGGER_LOG_FILENAME,
- BXP_CMOS_PATH,
- BXP_CMOS_IMAGE,
- BXP_CLOCK,
- BXP_CLOCK_TIME0,
- BXP_CLOCK_SYNC,
- BXP_LOAD32BITOS_WHICH,
- BXP_LOAD32BITOS_PATH,
- BXP_LOAD32BITOS_IOLOG,
- BXP_LOAD32BITOS_INITRD,
- BXP_LOAD32BITOS,
- BXP_BOOTDRIVE,
- BXP_FLOPPYSIGCHECK,
- BXP_MENU_MAIN,
- BXP_MENU_MEMORY,
- BXP_MENU_INTERFACE,
- BXP_MENU_DISK,
- BXP_MENU_SERIAL_PARALLEL,
- BXP_MENU_SOUND,
- BXP_MENU_KEYBOARD,
- BXP_MENU_MISC,
- BXP_MENU_MISC_2,
- BXP_MENU_RUNTIME,
- BXP_MAX_IPS,
- BXP_NE2K_PRESENT,
- BXP_NE2K_IOADDR,
- BXP_NE2K_IRQ,
- BXP_NE2K_MACADDR,
- BXP_NE2K_ETHMOD,
- BXP_NE2K_ETHDEV,
- BXP_NE2K_SCRIPT,
- BXP_NE2K,
- BXP_SB16_PRESENT,
- BXP_SB16_MIDIFILE,
- BXP_SB16_WAVEFILE,
- BXP_SB16_LOGFILE,
- BXP_SB16_MIDIMODE,
- BXP_SB16_WAVEMODE,
- BXP_SB16_LOGLEVEL,
- BXP_SB16_DMATIMER,
- BXP_SB16,
-#define BXP_PARAMS_PER_PARALLEL_PORT 2
- BXP_PARPORT1_ENABLED,
- BXP_PARPORT1_OUTFILE,
- BXP_PARPORT2_ENABLED,
- BXP_PARPORT2_OUTFILE,
- BXP_KEYBOARD_USEMAPPING,
- BXP_KEYBOARD_MAP,
- BXP_KEYBOARD,
- BXP_USER_SHORTCUT,
- BXP_ASK_FOR_PATHNAME, // for general file selection dialog
- BXP_BOCHS_START, // How Bochs starts
- // experiment: add params for CPU registers
- BXP_CPU_PARAMETERS,
- BXP_CPU_EAX,
- BXP_CPU_EBX,
- BXP_CPU_ECX,
- BXP_CPU_EDX,
- BXP_CPU_EBP,
- BXP_CPU_ESI,
- BXP_CPU_EDI,
- BXP_CPU_ESP,
- BXP_CPU_EIP,
- BXP_CPU_SEG_CS,
- BXP_CPU_SEG_DS,
- BXP_CPU_SEG_SS,
- BXP_CPU_SEG_ES,
- BXP_CPU_SEG_FS,
- BXP_CPU_SEG_GS,
- BXP_CPU_SEG_LDTR,
- BXP_CPU_SEG_TR,
- BXP_CPU_GDTR_BASE,
- BXP_CPU_GDTR_LIMIT,
- BXP_CPU_IDTR_BASE,
- BXP_CPU_IDTR_LIMIT,
- BXP_CPU_EFLAGS,
- BXP_CPU_EFLAGS_ID,
- BXP_CPU_EFLAGS_VIP,
- BXP_CPU_EFLAGS_VIF,
- BXP_CPU_EFLAGS_AC,
- BXP_CPU_EFLAGS_VM,
- BXP_CPU_EFLAGS_RF,
- BXP_CPU_EFLAGS_NT,
- BXP_CPU_EFLAGS_IOPL,
- BXP_CPU_EFLAGS_OF,
- BXP_CPU_EFLAGS_DF,
- BXP_CPU_EFLAGS_IF,
- BXP_CPU_EFLAGS_TF,
- BXP_CPU_EFLAGS_SF,
- BXP_CPU_EFLAGS_ZF,
- BXP_CPU_EFLAGS_AF,
- BXP_CPU_EFLAGS_PF,
- BXP_CPU_EFLAGS_CF,
- BXP_CPU_DR0,
- BXP_CPU_DR1,
- BXP_CPU_DR2,
- BXP_CPU_DR3,
- BXP_CPU_DR6,
- BXP_CPU_DR7,
- BXP_CPU_TR3,
- BXP_CPU_TR4,
- BXP_CPU_TR5,
- BXP_CPU_TR6,
- BXP_CPU_TR7,
- BXP_CPU_CR0,
- BXP_CPU_CR1,
- BXP_CPU_CR2,
- BXP_CPU_CR3,
- BXP_CPU_CR4,
- // a few parameters for the keyboard
- BXP_KBD_PARAMETERS,
- BXP_KBD_PARE,
- BXP_KBD_TIM ,
- BXP_KBD_AUXB,
- BXP_KBD_KEYL,
- BXP_KBD_C_D,
- BXP_KBD_SYSF,
- BXP_KBD_INPB,
- BXP_KBD_OUTB,
- BXP_KBD_TIMER_PENDING,
- BXP_KBD_IRQ1_REQ,
- BXP_KBD_IRQ12_REQ,
-#if BX_DEBUGGER
- // in debugger, is the simulation running (continue command) or waiting.
- // This is only modified by debugger code, not by the user.
- BXP_DEBUG_RUNNING,
-#endif
- BXP_SEL_CONFIG_INTERFACE,
- BXP_SEL_DISPLAY_LIBRARY,
- BXP_THIS_IS_THE_LAST // used to determine length of list
-} bx_id;
-
-// use x=1,2,3,4
-#define BXP_COMx_ENABLED(x) \
- (bx_id)(BXP_COM1_ENABLED + (((x)-1)*BXP_PARAMS_PER_SERIAL_PORT))
-#define BXP_COMx_PATH(x) \
- (bx_id)(BXP_COM1_PATH + (((x)-1)*BXP_PARAMS_PER_SERIAL_PORT))
-
-// use x=1
-#define BXP_USBx_ENABLED(x) \
- (bx_id)(BXP_USB1_ENABLED + (((x)-1)*BXP_PARAMS_PER_USB_HUB))
-#define BXP_USBx_IOADDR(x) \
- (bx_id)(BXP_USB1_IOADDR + (((x)-1)*BXP_PARAMS_PER_USB_HUB))
-#define BXP_USBx_IRQ(x) \
- (bx_id)(BXP_USB1_IRQ + (((x)-1)*BXP_PARAMS_PER_USB_HUB))
-
-// use x=1,2
-#define BXP_PARPORTx_ENABLED(x) \
- (bx_id)(BXP_PARPORT1_ENABLED + (((x)-1)*BXP_PARAMS_PER_PARALLEL_PORT))
-#define BXP_PARPORTx_OUTFILE(x) \
- (bx_id)(BXP_PARPORT1_OUTFILE + (((x)-1)*BXP_PARAMS_PER_PARALLEL_PORT))
-
-typedef enum {
- BX_TOOLBAR_UNDEFINED,
- BX_TOOLBAR_FLOPPYA,
- BX_TOOLBAR_FLOPPYB,
- BX_TOOLBAR_CDROMD,
- BX_TOOLBAR_RESET,
- BX_TOOLBAR_POWER,
- BX_TOOLBAR_COPY,
- BX_TOOLBAR_PASTE,
- BX_TOOLBAR_SNAPSHOT,
- BX_TOOLBAR_CONFIG,
- BX_TOOLBAR_MOUSE_EN,
- BX_TOOLBAR_USER
-} bx_toolbar_buttons;
-
-// Log level defines
-typedef enum {
- LOGLEV_DEBUG = 0,
- LOGLEV_INFO,
- LOGLEV_ERROR,
- LOGLEV_PANIC,
- LOGLEV_PASS,
- N_LOGLEV
-} bx_log_levels;
-
-// types of reset
-#define BX_RESET_SOFTWARE 10
-#define BX_RESET_HARDWARE 11
-
-//cdrom
-#define BX_EJECTED 10
-#define BX_INSERTED 11
-
-// boot devices
-#define BX_BOOT_FLOPPYA 0
-#define BX_BOOT_DISKC 1
-#define BX_BOOT_CDROM 2
-
-// loader hack
-#define Load32bitOSNone 0
-#define Load32bitOSLinux 1
-#define Load32bitOSNullKernel 2 // being developed for plex86
-#define Load32bitOSLast 2
-
-///////////////////////////////////////////////////////////////////
-// event structures for communication between simulator and CI
-///////////////////////////////////////////////////////////////////
-// Because the CI (configuration interface) might be in a different
-// thread or even a different process, we pass events encoded in data
-// structures to it instead of just calling functions. Each type of
-// event is declared as a different structure, and then all those
-// structures are squished into a union in BxEvent. (BTW, this is
-// almost exactly how X windows event structs work.)
-//
-// These are simple structs, unblemished by C++ methods and tricks.
-// No matter what event type it is, we allocate a BxEvent for each
-// one, as opposed to trying to save a few bytes on small events by
-// allocating only the bytes necessary for it. This makes it easy and
-// fast to store events in a queue, like this
-// BxEvent event_queue[MAX_EVENTS];
-//
-// Events come in two varieties: synchronous and asynchronous. We
-// have to worry about sync and async events because the CI and the
-// simulation may be running in different threads. An async event is
-// the simplest. Whichever thread originates the event just builds
-// the data structure, sends it, and then continues with its business.
-// Async events can go in either direction. Synchronous events
-// require the other thread to "respond" before the originating thread
-// can continue. It's like a function with a return value; you can't
-// continue until you get the return value back.
-//
-// Examples:
-//
-// async event: In the wxWindows implementation, both the CI and the
-// VGAW operate in the wxWindows GUI thread. When the user presses a
-// key, wxWindows sends a wxKeyEvent to the VGAW event handler code in
-// wx.cc. The VGAW handler then builds a BxEvent with
-// type=BX_ASYNC_EVT_KEY, and fills in the bx_key and raw_scancode
-// fields. The asynchronous event is placed on the event_queue for
-// the simulator, then the VGAW handler returns. (With wxWindows and
-// many other graphical libaries, the event handler must return
-// quickly because the window will not be updated until it's done.)
-// Some time later, the simulator reaches the point where it checks
-// for new events from the user (actually controlled by
-// bx_keyb_c::periodic() in iodev/keyboard.cc) and calls
-// bx_gui.handle_events(). Then all the events in the queue are
-// processed by the simulator. There is no "response" sent back to
-// the originating thread.
-//
-// sync event: Sometimes the simulator reaches a point where it needs
-// to ask the user how to proceed. In this case, the simulator sends
-// a synchronous event because it requires a response before it can
-// continue. It builds an event structure, perhaps with type
-// BX_SYNC_EVT_ASK_PARAM, sends it to the user interface
-// using the event handler function defined by set_notify_callback(),
-// and pauses the simulation. The user interface asks the user the
-// question, and puts the answer into the BxEvent.retcode field. The
-// event handler function returns the modified BxEvent with retcode
-// filled in, and the simulation continues. The details of this
-// transaction can be complicated if the simulation and CI are not
-// in the same thread, but the behavior is as described.
-//
-
-///// types and definitions used in event structures
-
-#define BX_EVT_IS_ASYNC(type) ((type) > __ALL_EVENTS_BELOW_ARE_ASYNC__)
-
-typedef enum {
- __ALL_EVENTS_BELOW_ARE_SYNCHRONOUS__ = 2000,
- BX_SYNC_EVT_GET_PARAM, // CI -> simulator -> CI
- BX_SYNC_EVT_ASK_PARAM, // simulator -> CI -> simulator
- BX_SYNC_EVT_TICK, // simulator -> CI, wait for response.
- BX_SYNC_EVT_LOG_ASK, // simulator -> CI, wait for response.
- BX_SYNC_EVT_GET_DBG_COMMAND, // simulator -> CI, wait for response.
- __ALL_EVENTS_BELOW_ARE_ASYNC__,
- BX_ASYNC_EVT_KEY, // vga window -> simulator
- BX_ASYNC_EVT_MOUSE, // vga window -> simulator
- BX_ASYNC_EVT_SET_PARAM, // CI -> simulator
- BX_ASYNC_EVT_LOG_MSG, // simulator -> CI
- BX_ASYNC_EVT_DBG_MSG, // simulator -> CI
- BX_ASYNC_EVT_VALUE_CHANGED, // simulator -> CI
- BX_ASYNC_EVT_TOOLBAR, // CI -> simulator
- BX_ASYNC_EVT_REFRESH // simulator -> CI
-} BxEventType;
-
-typedef union {
- Bit32s s32;
- char *charptr;
-} AnyParamVal;
-
-// Define substructures which make up the interior of BxEvent. The
-// substructures, such as BxKeyEvent or BxMouseEvent, should never be
-// allocated on their own. They are only intended to be used within
-// the union in the BxEvent structure.
-
-// Event type: BX_SYNC_EVT_TICK
-//
-// A tick event is synchronous, sent from the simulator to the GUI. The
-// event doesn't do anything visible. Primarily it gives the GUI a chance
-// to tell the simulator to quit, if necessary. There may be other uses
-// for the tick in the future, such as giving some kind of regular
-// status report or mentioning watched values that changed, but so far
-// it's just for that one thing. There is no data associated with a
-// tick event.
-
-// Event type: BX_ASYNC_EVT_KEY
-//
-// A key event can be sent from the VGA window to the Bochs simulator.
-// It is asynchronous.
-typedef struct {
- // what was pressed? This is a BX_KEY_* value. For key releases,
- // BX_KEY_RELEASED is ORed with the base BX_KEY_*.
- Bit32u bx_key;
- bx_bool raw_scancode;
-} BxKeyEvent;
-
-// Event type: BX_ASYNC_EVT_MOUSE
-//
-// A mouse event can be sent from the VGA window to the Bochs
-// simulator. It is asynchronous. Currently unused because mouse
-// events aren't implemented in our wxWindows code yet.
-typedef struct {
- // type is BX_EVT_MOUSE
- Bit16s dx, dy; // mouse motion delta
- Bit8u buttons; // which buttons are pressed.
- // bit 0: 1=left button down, 0=up
- // bit 1: 1=right button down, 0=up
-} BxMouseEvent;
-
-// Event type: BX_SYNC_EVT_GET_PARAM, BX_ASYNC_EVT_SET_PARAM
-//
-// Parameter set/get events are initiated by the CI, since Bochs can
-// always access the parameters directly. So far, I haven't used
-// these event types. In the CI I just call
-// SIM->get_param(parameter_id) to get a pointer to the bx_param_c
-// object and then call the get/set methods. This is okay for
-// configuration since bochs is not running. However it could be
-// dangerous for the GUI thread to poke around in Bochs structures
-// while the thread is running. For these cases, I may have to be
-// more careful and actually build get/set events and place them on
-// Bochs's event queue to be processed during SIM->periodic() or
-// something.
-typedef struct {
- // type is BX_EVT_GET_PARAM, BX_EVT_SET_PARAM
- class bx_param_c *param; // pointer to param structure
- AnyParamVal val;
-} BxParamEvent;
-
-// Event type: BX_SYNC_EVT_ASK_PARAM
-// Synchronous event sent from the simulator to the CI. This tells the
-// CI to ask the user to choose the value of a parameter. The CI may
-// need to discover the type of parameter so that it can use the right
-// kind of graphical display. The BxParamEvent is used for these events
-// too.
-// FIXME: at the moment the GUI implements the ASK_PARAM event for just
-// a few parameter types. I need to implement the event for all parameter
-// types.
-
-// Event type: BX_ASYNC_EVT_VALUE_CHANGED
-//
-// Asynchronous event sent from the simulator to the CI, telling it that
-// some value that it (hopefully) cares about has changed. This isn't
-// being used yet, but a good example is in a debugger interface, you might
-// want to maintain a reasonably current display of the PC or some other
-// simulation state. The CI would set some kind of event mask (which
-// doesn't exist now of course) and then when certain values change, the
-// simulator would send this event so that the CI can update. We may need
-// some kind of "flow control" since the simulator will be able to produce
-// new events much faster than the gui can accept them.
-
-// Event type: BX_ASYNC_EVT_LOG_MSG (unused)
-//
-// Asynchronous event from the simulator to the CI. When a BX_PANIC,
-// BX_ERROR, BX_INFO, or BX_DEBUG is found in the simulator code, this
-// event type can be used to inform the CI of the condition. There is
-// no point in sending messages to the CI that will not be displayed; these
-// would only slow the simulation. So we will need some mechanism for
-// choosing what kinds of events will be delivered to the CI. Normally,
-// you wouldn't want to look at the log unless something is going wrong.
-// At that point, you might want to open up a window to watch the debug
-// messages from one or two devices only.
-//
-// Idea: Except for panics that require user attention to continue, it
-// might be most efficient to just append log messages to a file.
-// When the user wants to look at the log messages, the gui can reopen
-// the file (read only), skip to the end, and look backward for a
-// reasonable number of lines to display (200?). This allows it to
-// skip over huge bursts of log entries without allocating memory,
-// synchronizing threads, etc. for each.
-typedef struct {
- Bit8u level;
- const char *prefix;
- const char *msg;
-} BxLogMsgEvent;
-
-// Event type: BX_ASYNC_EVT_DBG_MSG (unused)
-//
-// Also uses BxLogMsgEvent, but this is a message to be displayed in
-// the debugger history window.
-
-// Event type: BX_SYNC_EVT_LOG_ASK
-//
-// This is a synchronous version of BX_ASYNC_EVT_LOG_MSG, which is used
-// when the "action=ask" setting is used. If the simulator runs into a
-// panic, it sends a synchronous BX_SYNC_EVT_LOG_ASK to the CI to be
-// displayed. The CI shows a dialog that asks if the user wants to
-// continue, quit, etc. and sends the answer back to the simulator.
-// This event also uses BxLogMsgEvent.
-enum {
- BX_LOG_ASK_CHOICE_CONTINUE,
- BX_LOG_ASK_CHOICE_CONTINUE_ALWAYS,
- BX_LOG_ASK_CHOICE_DIE,
- BX_LOG_ASK_CHOICE_DUMP_CORE,
- BX_LOG_ASK_CHOICE_ENTER_DEBUG,
- BX_LOG_ASK_N_CHOICES
-};
-
-// Event type: BX_SYNC_EVT_GET_DBG_COMMAND
-//
-// This is a synchronous event sent from the simulator to the debugger
-// requesting the next action. In a text mode debugger, this would prompt
-// the user for the next command. When a new command is ready, the
-// synchronous event is sent back with its fields filled in.
-typedef struct {
- char *command; // null terminated string. allocated by debugger interface
- // with new operator, freed by simulator with delete.
-} BxDebugCommand;
-
-
-
-// Event type: BX_EVT_TOOLBAR
-// Asynchronous event from the VGAW to the simulator, sent when the user
-// clicks on a toolbar button. This may one day become something more
-// general, like a command event, but at the moment it's only needed for
-// the toolbar events.
-typedef struct {
- bx_toolbar_buttons button;
- bool on; // for toggling buttons, on=true means the toolbar button is
- // pressed. on=false means it is not pressed.
-} BxToolbarEvent;
-
-// The BxEvent structure should be used for all events. Every event has
-// a type and a spot for a return code (only used for synchronous events).
-typedef struct {
- BxEventType type; // what kind is this?
- Bit32s retcode; // sucess or failure. only used for synchronous events.
- union {
- BxKeyEvent key;
- BxMouseEvent mouse;
- BxParamEvent param;
- BxLogMsgEvent logmsg;
- BxToolbarEvent toolbar;
- BxDebugCommand debugcmd;
- } u;
-} BxEvent;
-
-
-////////////////////////////////////////////////////////////////////
-// parameter classes: bx_param_c and family
-////////////////////////////////////////////////////////////////////
-//
-// All variables that can be configured through the CI are declared as
-// "parameters" or objects of type bx_param_*. There is a bx_param_*
-// class for each type of data that the user would need to see and
-// edit, e.g. integer, boolean, enum, string, filename, or list of
-// other parameters. The purpose of the bx_param_* class, in addition
-// to storing the parameter's value, is to hold the name, description,
-// and constraints on the value. The bx_param_* class should hold
-// everything that the CI would need to display the value and allow
-// the user to modify it. For integer parameters, the minimum and
-// maximum allowed value can be defined, and the base in which it
-// should be displayed and interpreted. For enums, the
-// bx_param_enum_c structure includes the list of values which the
-// parameter can have.
-//
-// Also, some parameter classes support get/set callback functions to
-// allow arbitrary code to be executed when the parameter is get/set.
-// An example of where this is useful: if you disable the NE2K card,
-// the set() handler for that parameter can tell the user interface
-// that the NE2K's irq, I/O address, and mac address should be
-// disabled (greyed out, hidden, or made inaccessible). The get/set
-// methods can also check if the set() value is acceptable using
-// whatever means and override it.
-//
-// The parameter concept is similar to the use of parameters in JavaBeans.
-
-class bx_object_c;
-class bx_param_c;
-class bx_param_num_c;
-class bx_param_enum_c;
-class bx_param_bool_c;
-class bx_param_string_c;
-class bx_param_filename_c;
-class bx_list_c;
-
-class BOCHSAPI bx_object_c {
-private:
- bx_id id;
- bx_objtype type;
-protected:
- void set_type (bx_objtype type);
-public:
- bx_object_c (bx_id id);
- bx_id get_id () { return id; }
- Bit8u get_type () { return type; }
-};
-
-class BOCHSAPI bx_param_c : public bx_object_c {
- BOCHSAPI_CYGONLY static const char *default_text_format;
-protected:
- char *name;
- char *description;
- char *label; // label string for text menus and gui dialogs
- const char *text_format; // printf format string. %d for ints, %s for strings, etc.
- char *ask_format; // format string for asking for a new value
- int runtime_param;
- int enabled;
-public:
- bx_param_c (bx_id id, char *name, char *description);
- void set_format (const char *format) {text_format = format;}
- const char *get_format () {return text_format;}
- void set_ask_format (char *format) {ask_format = format; }
- char *get_ask_format () {return ask_format;}
- void set_label (char *text) {label = text;}
- char *get_label () {return label;}
- void set_runtime_param (int val) { runtime_param = val; }
- int get_runtime_param () { return runtime_param; }
- char *get_name () { return name; }
- char *get_description () { return description; }
- int get_enabled () { return enabled; }
- virtual void set_enabled (int enabled) { this->enabled = enabled; }
- void reset () {}
- int getint () {return -1;}
- static const char* set_default_format (const char *f);
- static const char *get_default_format () { return default_text_format; }
- virtual bx_list_c *get_dependent_list () { return NULL; }
-#if BX_UI_TEXT
- virtual void text_print (FILE *fp) {}
- virtual int text_ask (FILE *fpin, FILE *fpout) {return -1;}
-#endif
-};
-
-typedef Bit64s (*param_event_handler)(class bx_param_c *, int set, Bit64s val);
-typedef int (*param_enable_handler)(class bx_param_c *, int en);
-
-class BOCHSAPI bx_param_num_c : public bx_param_c {
- BOCHSAPI_CYGONLY static Bit32u default_base;
- // The dependent_list is initialized to NULL. If dependent_list is modified
- // to point to a bx_list_c of other parameters, the set() method of
- // bx_param_bool_c will enable those parameters when this bool is true, and
- // disable them when this bool is false.
- bx_list_c *dependent_list;
- void update_dependents ();
-protected:
- Bit64s min, max, initial_val;
- union _uval_ {
- Bit64s number; // used by bx_param_num_c
- Bit64s *p64bit; // used by bx_shadow_num_c
- Bit32s *p32bit; // used by bx_shadow_num_c
- Bit16s *p16bit; // used by bx_shadow_num_c
- Bit8s *p8bit; // used by bx_shadow_num_c
- bx_bool *pbool; // used by bx_shadow_bool_c
- } val;
- param_event_handler handler;
- param_enable_handler enable_handler;
- int base;
- Bit32u options;
-public:
- enum {
- // When a bx_param_num_c is displayed in dialog, USE_SPIN_CONTROL controls
- // whether a spin control should be used instead of a simple text control.
- USE_SPIN_CONTROL = (1<<0)
- } bx_numopt_bits;
- bx_param_num_c (bx_id id,
- char *name,
- char *description,
- Bit64s min, Bit64s max, Bit64s initial_val);
- void reset ();
- void set_handler (param_event_handler handler);
- void set_enable_handler (param_enable_handler handler);
- virtual bx_list_c *get_dependent_list () { return dependent_list; }
- void set_dependent_list (bx_list_c *l);
- virtual void set_enabled (int enabled);
- virtual Bit32s get () { return (Bit32s) get64(); }
- virtual Bit64s get64 ();
- virtual void set (Bit64s val);
- void set_base (int base) { this->base = base; }
- void set_initial_val (Bit64s initial_val);
- int get_base () { return base; }
- void set_range (Bit64u min, Bit64u max);
- Bit64s get_min () { return min; }
- Bit64s get_max () { return max; }
- static Bit32u set_default_base (Bit32u val);
- static Bit32u get_default_base () { return default_base; }
- void set_options (Bit32u options) { this->options = options; }
- Bit32u get_options () { return options; }
-#if BX_UI_TEXT
- virtual void text_print (FILE *fp);
- virtual int text_ask (FILE *fpin, FILE *fpout);
-#endif
-};
-
-// a bx_shadow_num_c is like a bx_param_num_c except that it doesn't
-// store the actual value with its data. Instead, it uses val.p32bit
-// to keep a pointer to the actual data. This is used to register
-// existing variables as parameters, without have to access it via
-// set/get methods.
-class BOCHSAPI bx_shadow_num_c : public bx_param_num_c {
- Bit8u varsize; // must be 64, 32, 16, or 8
- Bit8u lowbit; // range of bits associated with this param
- Bit64u mask; // mask is ANDed with value before it is returned from get
-public:
- bx_shadow_num_c (bx_id id,
- char *name,
- char *description,
- Bit64s *ptr_to_real_val,
- Bit8u highbit = 63,
- Bit8u lowbit = 0);
- bx_shadow_num_c (bx_id id,
- char *name,
- char *description,
- Bit64u *ptr_to_real_val,
- Bit8u highbit = 63,
- Bit8u lowbit = 0);
- bx_shadow_num_c (bx_id id,
- char *name,
- char *description,
- Bit32s *ptr_to_real_val,
- Bit8u highbit = 31,
- Bit8u lowbit = 0);
- bx_shadow_num_c (bx_id id,
- char *name,
- char *description,
- Bit32u *ptr_to_real_val,
- Bit8u highbit = 31,
- Bit8u lowbit = 0);
- bx_shadow_num_c (bx_id id,
- char *name,
- char *description,
- Bit16s *ptr_to_real_val,
- Bit8u highbit = 15,
- Bit8u lowbit = 0);
- bx_shadow_num_c (bx_id id,
- char *name,
- char *description,
- Bit16u *ptr_to_real_val,
- Bit8u highbit = 15,
- Bit8u lowbit = 0);
- bx_shadow_num_c (bx_id id,
- char *name,
- char *description,
- Bit8s *ptr_to_real_val,
- Bit8u highbit = 7,
- Bit8u lowbit = 0);
- bx_shadow_num_c (bx_id id,
- char *name,
- char *description,
- Bit8u *ptr_to_real_val,
- Bit8u highbit = 7,
- Bit8u lowbit = 0);
- virtual Bit64s get64 ();
- virtual void set (Bit64s val);
-};
-
-class BOCHSAPI bx_param_bool_c : public bx_param_num_c {
- // many boolean variables are used to enable/disable modules. In the
- // user interface, the enable variable should enable/disable all the
- // other parameters associated with that module.
-public:
- bx_param_bool_c (bx_id id,
- char *name,
- char *description,
- Bit64s initial_val);
-#if BX_UI_TEXT
- virtual void text_print (FILE *fp);
- virtual int text_ask (FILE *fpin, FILE *fpout);
-#endif
-};
-
-// a bx_shadow_bool_c is a shadow param based on bx_param_bool_c.
-class BOCHSAPI bx_shadow_bool_c : public bx_param_bool_c {
- // each bit of a bitfield can be a separate value. bitnum tells which
- // bit is used. get/set will only modify that bit.
- Bit8u bitnum;
-public:
- bx_shadow_bool_c (bx_id id,
- char *name,
- char *description,
- bx_bool *ptr_to_real_val,
- Bit8u bitnum = 0);
- virtual Bit64s get64 ();
- virtual void set (Bit64s val);
-};
-
-
-class BOCHSAPI bx_param_enum_c : public bx_param_num_c {
- char **choices;
-public:
- bx_param_enum_c (bx_id id,
- char *name,
- char *description,
- char **choices,
- Bit64s initial_val,
- Bit64s value_base = 0);
- char *get_choice (int n) { return choices[n]; }
- int find_by_name (const char *string);
- bool set_by_name (const char *string);
-#if BX_UI_TEXT
- virtual void text_print (FILE *fp);
- virtual int text_ask (FILE *fpin, FILE *fpout);
-#endif
-};
-
-typedef char* (*param_string_event_handler)(class bx_param_string_c *, int set, char *val, int maxlen);
-
-class BOCHSAPI bx_param_string_c : public bx_param_c {
- int maxsize;
- char *val, *initial_val;
- param_string_event_handler handler;
- param_enable_handler enable_handler;
- bx_param_num_c *options;
- char separator;
-public:
- enum {
- RAW_BYTES = 1, // use binary text editor, like MAC addr
- IS_FILENAME = 2, // 1=yes it's a filename, 0=not a filename.
- // Some guis have a file browser. This
- // bit suggests that they use it.
- SAVE_FILE_DIALOG = 4 // Use save dialog opposed to open file dialog
- } bx_string_opt_bits;
- bx_param_string_c (bx_id id,
- char *name,
- char *description,
- char *initial_val,
- int maxsize=-1);
- virtual ~bx_param_string_c ();
- void reset ();
- void set_handler (param_string_event_handler handler);
- void set_enable_handler (param_enable_handler handler);
- virtual void set_enabled (int enabled);
- Bit32s get (char *buf, int len);
- char *getptr () {return val; }
- void set (char *buf);
- bx_bool equals (const char *buf);
- bx_param_num_c *get_options () { return options; }
- void set_separator (char sep) {separator = sep; }
- char get_separator () {return separator; }
- int get_maxsize () {return maxsize; }
-#if BX_UI_TEXT
- virtual void text_print (FILE *fp);
- virtual int text_ask (FILE *fpin, FILE *fpout);
-#endif
-};
-
-// Declare a filename class. It is identical to a string, except that
-// it initializes the options differently. This is just a shortcut
-// for declaring a string param and setting the options with IS_FILENAME.
-class BOCHSAPI bx_param_filename_c : public bx_param_string_c {
-public:
- bx_param_filename_c (bx_id id,
- char *name,
- char *description,
- char *initial_val,
- int maxsize=-1);
-};
-
-class BOCHSAPI bx_list_c : public bx_param_c {
-private:
- // just a list of bx_param_c objects. size tells current number of
- // objects in the list, and maxsize tells how many list items are
- // allocated in the constructor.
- bx_param_c **list;
- int size, maxsize;
- // options is a bit field whose bits are defined by bx_listopt_bits ORed
- // together. Options is a bx_param so that if necessary the bx_list could
- // install a handler to cause get/set of options to have side effects.
- bx_param_num_c *options;
- // for a menu, the value of choice before the call to "ask" is default.
- // After ask, choice holds the value that the user chose. Choice defaults
- // to 1 in the constructor.
- bx_param_num_c *choice;
- // title of the menu or series
- bx_param_string_c *title;
- // if the menu shows a "return to previous menu" type of choice,
- // this controls where that choice will go.
- bx_param_c *parent;
- void init ();
-public:
- enum {
- // When a bx_list_c is displayed as a menu, SHOW_PARENT controls whether or
- // not the menu shows a "Return to parent menu" choice or not.
- SHOW_PARENT = (1<<0),
- // Some lists are best displayed shown as menus, others as a series of
- // related questions. This bit suggests to the CI that the series of
- // questions format is preferred.
- SERIES_ASK = (1<<1),
- // When a bx_list_c is displayed in a dialog, USE_TAB_WINDOW suggests
- // to the CI that each item in the list should be shown as a separate
- // tab. This would be most appropriate when each item is another list
- // of parameters.
- USE_TAB_WINDOW = (1<<2),
- // When a bx_list_c is displayed in a dialog, the list name is used as the
- // label of the group box if USE_BOX_TITLE is set. This is only necessary if
- // more than one list appears in a dialog box.
- USE_BOX_TITLE = (1<<3)
- } bx_listopt_bits;
- bx_list_c (bx_id id, int maxsize);
- bx_list_c (bx_id id, char *name, char *description, bx_param_c **init_list);
- bx_list_c (bx_id id, char *name, char *description, int maxsize);
- virtual ~bx_list_c();
- bx_list_c *clone ();
- void add (bx_param_c *param);
- bx_param_c *get (int index);
- int get_size () { return size; }
- bx_param_num_c *get_options () { return options; }
- void set_options (bx_param_num_c *newopt) { options = newopt; }
- bx_param_num_c *get_choice () { return choice; }
- bx_param_string_c *get_title () { return title; }
- void set_parent (bx_param_c *newparent) { parent = newparent; }
- bx_param_c *get_parent () { return parent; }
-#if BX_UI_TEXT
- virtual void text_print (FILE *);
- virtual int text_ask (FILE *fpin, FILE *fpout);
-#endif
-};
-
-////////////////////////////////////////////////////////////////
-
-
-// These are the different start modes.
-enum {
- // Just start the simulation without running the configuration interface
- // at all, unless something goes wrong.
- BX_QUICK_START = 200,
- // Run the configuration interface. The default action will be to load a
- // configuration file. This makes sense if a config file could not be
- // loaded, either because it wasn't found or because it had errors.
- BX_LOAD_START,
- // Run the configuration interface. The default action will be to
- // edit the configuration.
- BX_EDIT_START,
- // Run the configuration interface, but make the default action be to
- // start the simulation.
- BX_RUN_START
-};
-
-#define BX_FLOPPY_NONE 10 // floppy not present
-#define BX_FLOPPY_1_2 11 // 1.2M 5.25"
-#define BX_FLOPPY_1_44 12 // 1.44M 3.5"
-#define BX_FLOPPY_2_88 13 // 2.88M 3.5"
-#define BX_FLOPPY_720K 14 // 720K 3.5"
-#define BX_FLOPPY_360K 15 // 360K 5.25"
-#define BX_FLOPPY_160K 16 // 160K 5.25"
-#define BX_FLOPPY_180K 17 // 180K 5.25"
-#define BX_FLOPPY_320K 18 // 320K 5.25"
-#define BX_FLOPPY_LAST 18 // last legal value of floppy type
-
-#define BX_FLOPPY_GUESS 20 // decide based on image size
-
-#define BX_ATA_DEVICE_DISK 0
-#define BX_ATA_DEVICE_CDROM 1
-#define BX_ATA_DEVICE_LAST 1
-
-#define BX_ATA_BIOSDETECT_NONE 0
-#define BX_ATA_BIOSDETECT_AUTO 1
-#define BX_ATA_BIOSDETECT_CMOS 2
-
-#define BX_ATA_TRANSLATION_NONE 0
-#define BX_ATA_TRANSLATION_LBA 1
-#define BX_ATA_TRANSLATION_LARGE 2
-#define BX_ATA_TRANSLATION_RECHS 3
-#define BX_ATA_TRANSLATION_AUTO 4
-#define BX_ATA_TRANSLATION_LAST 4
-
-#define BX_ATA_MODE_FLAT 0
-#define BX_ATA_MODE_CONCAT 1
-#define BX_ATA_MODE_EXTDISKSIM 2
-#define BX_ATA_MODE_DLL_HD 3
-#define BX_ATA_MODE_SPARSE 4
-#define BX_ATA_MODE_VMWARE3 5
-#define BX_ATA_MODE_UNDOABLE 6
-#define BX_ATA_MODE_GROWING 7
-#define BX_ATA_MODE_VOLATILE 8
-#define BX_ATA_MODE_LAST 8
-//#define BX_ATA_MODE_Z_UNDOABLE 9
-//#define BX_ATA_MODE_Z_VOLATILE 10
-//#define BX_ATA_MODE_SPLIT 6
-
-#define BX_CLOCK_SYNC_NONE 0
-#define BX_CLOCK_SYNC_REALTIME 1
-#define BX_CLOCK_SYNC_SLOWDOWN 2
-#define BX_CLOCK_SYNC_BOTH 3
-#define BX_CLOCK_SYNC_LAST 3
-
-#define BX_CLOCK_TIME0_LOCAL 1
-#define BX_CLOCK_TIME0_UTC 2
-
-BOCHSAPI extern char *bochs_start_names[];
-BOCHSAPI extern int n_bochs_start_names;
-BOCHSAPI extern char *floppy_type_names[];
-BOCHSAPI extern int floppy_type_n_sectors[];
-BOCHSAPI extern int n_floppy_type_names;
-BOCHSAPI extern char *floppy_status_names[];
-BOCHSAPI extern int n_floppy_status_names;
-BOCHSAPI extern char *floppy_bootdisk_names[];
-BOCHSAPI extern int n_floppy_bootdisk_names;
-BOCHSAPI extern char *loader_os_names[];
-BOCHSAPI extern int n_loader_os_names;
-BOCHSAPI extern char *keyboard_type_names[];
-BOCHSAPI extern int n_keyboard_type_names;
-BOCHSAPI extern char *atadevice_type_names[];
-BOCHSAPI extern int n_atadevice_type_names;
-BOCHSAPI extern char *atadevice_mode_names[];
-BOCHSAPI extern int n_atadevice_mode_names;
-BOCHSAPI extern char *atadevice_status_names[];
-BOCHSAPI extern int n_atadevice_status_names;
-BOCHSAPI extern char *atadevice_biosdetect_names[];
-BOCHSAPI extern int n_atadevice_biosdetect_names;
-BOCHSAPI extern char *atadevice_translation_names[];
-BOCHSAPI extern int n_atadevice_translation_names;
-BOCHSAPI extern char *clock_sync_names[];
-BOCHSAPI extern int clock_sync_n_names;
-
-typedef struct {
- bx_param_enum_c *Odevtype;
- bx_param_string_c *Opath;
- bx_param_enum_c *Otype;
- bx_param_enum_c *Ostatus;
- } bx_floppy_options;
-
-typedef struct {
- bx_list_c *Omenu;
- bx_param_bool_c *Opresent;
- bx_param_enum_c *Otype;
- bx_param_enum_c *Omode;
- bx_param_string_c *Opath;
- bx_param_string_c *Ojournal;
- bx_param_num_c *Ocylinders;
- bx_param_num_c *Oheads;
- bx_param_num_c *Ospt;
- bx_param_enum_c *Ostatus;
- bx_param_string_c *Omodel;
- bx_param_enum_c *Obiosdetect;
- bx_param_enum_c *Otranslation;
- } bx_atadevice_options;
-
-typedef struct {
- bx_param_bool_c *Oenabled;
- bx_param_string_c *Odev;
- } bx_serial_options;
-
-typedef struct {
- bx_param_bool_c *Oenabled;
- bx_param_num_c *Oioaddr;
- bx_param_num_c *Oirq;
- } bx_usb_options;
-
-
-////////////////////////////////////////////////////////////////////
-// base class simulator interface, contains just virtual functions.
-// I'm not longer sure that having a base class is going to be of any
-// use... -Bryce
-
-#include <setjmp.h>
-
-enum ci_command_t { CI_START, CI_RUNTIME_CONFIG, CI_SHUTDOWN };
-enum ci_return_t {
- CI_OK, // normal return value
- CI_ERR_NO_TEXT_CONSOLE // err: can't work because there's no text console
- };
-typedef int (*config_interface_callback_t)(void *userdata, ci_command_t command);
-
-// bx_gui->set_display_mode() changes the mode between the configuration
-// interface and the simulation. This is primarily intended for display
-// libraries which have a full-screen mode such as SDL, term, and svgalib. The
-// display mode is set to DISP_MODE_CONFIG before displaying any configuration
-// menus, for panics that requires user input, when entering the debugger, etc.
-// It is set to DISP_MODE_SIM when the Bochs simulation resumes. The constants
-// are defined here so that configuration interfaces can use them with the
-// bx_simulator_interface_c::set_display_mode() method.
-enum disp_mode_t { DISP_MODE_CONFIG=100, DISP_MODE_SIM };
-
-class BOCHSAPI bx_simulator_interface_c {
-public:
- bx_simulator_interface_c ();
- virtual void set_quit_context (jmp_buf *context) {}
- virtual int get_init_done () { return -1; }
- virtual int set_init_done (int n) {return -1;}
- virtual void get_param_id_range (int *min, int *max) {}
- virtual int register_param (bx_id id, bx_param_c *it) {return -1;}
- virtual void reset_all_param () {}
- virtual bx_param_c *get_param (bx_id id) {return NULL;}
- virtual bx_param_num_c *get_param_num (bx_id id) {return NULL;}
- virtual bx_param_string_c *get_param_string (bx_id id) {return NULL;}
- virtual bx_param_bool_c *get_param_bool (bx_id id) {return NULL;}
- virtual bx_param_enum_c *get_param_enum (bx_id id) {return NULL;}
- virtual int get_n_log_modules () {return -1;}
- virtual char *get_prefix (int mod) {return 0;}
- virtual int get_log_action (int mod, int level) {return -1;}
- virtual void set_log_action (int mod, int level, int action) {}
- virtual int get_default_log_action (int level) {return -1;}
- virtual void set_default_log_action (int level, int action) {}
- virtual char *get_action_name (int action) {return 0;}
- virtual const char *get_log_level_name (int level) {return 0;}
- virtual int get_max_log_level () {return -1;}
-
- // exiting is somewhat complicated! The preferred way to exit bochs is
- // to call BX_EXIT(exitcode). That is defined to call
- // SIM->quit_sim(exitcode). The quit_sim function first calls
- // the cleanup functions in bochs so that it can destroy windows
- // and free up memory, then sends a notify message to the CI
- // telling it that bochs has stopped.
- virtual void quit_sim (int code) {}
-
- virtual int get_exit_code () { return 0; }
-
- virtual int get_default_rc (char *path, int len) {return -1;}
- virtual int read_rc (char *path) {return -1;}
- virtual int write_rc (char *rc, int overwrite) {return -1;}
- virtual int get_log_file (char *path, int len) {return -1;}
- virtual int set_log_file (char *path) {return -1;}
- virtual int get_log_prefix (char *prefix, int len) {return -1;}
- virtual int set_log_prefix (char *prefix) {return -1;}
- virtual int get_debugger_log_file (char *path, int len) {return -1;}
- virtual int set_debugger_log_file (char *path) {return -1;}
- virtual int get_floppy_options (int drive, bx_floppy_options *out) {return -1;}
- virtual int get_cdrom_options (int drive, bx_atadevice_options *out, int *where = NULL) {return -1;}
- virtual char *get_floppy_type_name (int type) {return NULL;}
-
- // The CI calls set_notify_callback to register its event handler function.
- // This event handler function is called whenever the simulator needs to
- // send an event to the CI. For example, if the simulator hits a panic and
- // wants to ask the user how to proceed, it would call the CI event handler
- // to ask the CI to display a dialog.
- //
- // NOTE: At present, the standard VGAW buttons (floppy, snapshot, power,
- // etc.) are displayed and handled by gui.cc, not by the CI or siminterface.
- // gui.cc uses its own callback functions to implement the behavior of
- // the buttons. Some of these implementations call the siminterface.
- typedef BxEvent* (*bxevent_handler)(void *theclass, BxEvent *event);
- virtual void set_notify_callback (bxevent_handler func, void *arg) {}
- virtual void get_notify_callback (bxevent_handler *func, void **arg) {}
-
- // send an event from the simulator to the CI.
- virtual BxEvent* sim_to_ci_event (BxEvent *event) {return NULL;}
-
- // called from simulator when it hits serious errors, to ask if the user
- // wants to continue or not
- virtual int log_msg (const char *prefix, int level, const char *msg) {return -1;}
-
- // tell the CI to ask the user for the value of a parameter.
- virtual int ask_param (bx_id param) {return -1;}
-
- // ask the user for a pathname
- virtual int ask_filename (char *filename, int maxlen, char *prompt, char *the_default, int flags) {return -1;}
- // called at a regular interval, currently by the keyboard handler.
- virtual void periodic () {}
- virtual int create_disk_image (const char *filename, int sectors, bx_bool overwrite) {return -3;}
- // Tell the configuration interface (CI) that some parameter values have
- // changed. The CI will reread the parameters and change its display if it's
- // appropriate. Maybe later: mention which params have changed to save time.
- virtual void refresh_ci () {}
- // forces a vga update. This was added so that a debugger can force
- // a vga update when single stepping, without having to wait thousands
- // of cycles for the normal vga refresh triggered by iodev/keyboard.cc.
- virtual void refresh_vga () {}
- // forces a call to bx_gui.handle_events. This was added so that a debugger
- // can force the gui events to be handled, so that interactive things such
- // as a toolbar click will be processed.
- virtual void handle_events () {}
- // return first hard disk in ATA interface
- virtual bx_param_c *get_first_cdrom () {return NULL;}
- // return first cdrom in ATA interface
- virtual bx_param_c *get_first_hd () {return NULL;}
-#if BX_DEBUGGER
- // for debugger: same behavior as pressing control-C
- virtual void debug_break () {}
- virtual void debug_interpret_cmd (char *cmd) {}
- virtual char *debug_get_next_command () {return NULL;}
- virtual void debug_puts (const char *text) {}
-#endif
- virtual void register_configuration_interface (
- const char* name,
- config_interface_callback_t callback,
- void *userdata) {}
- virtual int configuration_interface(const char* name, ci_command_t command) {return -1; }
- virtual int begin_simulation (int argc, char *argv[]) {return -1;}
- typedef bool (*is_sim_thread_func_t)();
- is_sim_thread_func_t is_sim_thread_func;
- virtual void set_sim_thread_func (is_sim_thread_func_t func) {
- is_sim_thread_func = func;
- }
- virtual bool is_sim_thread () {return true;}
- virtual bool is_wx_selected () {return false;}
- // provide interface to bx_gui->set_display_mode() method for config
- // interfaces to use.
- virtual void set_display_mode (disp_mode_t newmode) {}
- virtual bool test_for_text_console () { return true; }
-};
-
-BOCHSAPI extern bx_simulator_interface_c *SIM;
-
-BOCHSAPI extern void bx_init_siminterface ();
-BOCHSAPI extern int bx_init_main (int argc, char *argv[]);
-
-#if defined(__WXMSW__) || defined(WIN32)
-// Just to provide HINSTANCE, etc. in files that have not included bochs.h.
-// I don't like this at all, but I don't see a way around it.
-#include <windows.h>
-#endif
-
-// define structure to hold data that is passed into our main function.
-typedef struct BOCHSAPI {
- // standard argc,argv
- int argc;
- char **argv;
-#ifdef WIN32
- char initial_dir[MAX_PATH];
-#endif
-#ifdef __WXMSW__
- // these are only used when compiling with wxWindows. This gives us a
- // place to store the data that was passed to WinMain.
- HINSTANCE hInstance;
- HINSTANCE hPrevInstance;
- LPSTR m_lpCmdLine;
- int nCmdShow;
-#endif
-} bx_startup_flags_t;
-
-BOCHSAPI extern bx_startup_flags_t bx_startup_flags;
-BOCHSAPI extern bx_bool bx_user_quit;
+++ /dev/null
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-#define _MULTI_THREAD
-
-// Define BX_PLUGGABLE in files that can be compiled into plugins. For
-// platforms that require a special tag on exported symbols, BX_PLUGGABLE
-// is used to know when we are exporting symbols and when we are importing.
-#define BX_PLUGGABLE
-
-#include "bochs.h"
-#if BX_WITH_SVGA
-
-#include <stdlib.h>
-#include </usr/include/vga.h>
-#include <vgagl.h>
-#include <vgakeyboard.h>
-#include <vgamouse.h>
-
-#include "font/vga.bitmap.h"
-//#include "icon_bochs.h"
-
-class bx_svga_gui_c : public bx_gui_c {
-public:
- bx_svga_gui_c (void);
- DECLARE_GUI_VIRTUAL_METHODS()
- virtual void set_display_mode (disp_mode_t newmode);
-};
-
-// declare one instance of the gui object and call macro to insert the
-// plugin code
-static bx_svga_gui_c *theGui = NULL;
-
-IMPLEMENT_GUI_PLUGIN_CODE(svga)
-
-#define LOG_THIS theGui->
-
-static unsigned res_x, res_y;
-static int fontwidth = 8, fontheight = 16;
-static unsigned tilewidth, tileheight;
-static unsigned char vgafont[256 * 16];
-static int clut8 = 0;
-GraphicsContext *screen = NULL;
-static int save_vga_mode;
-static int save_vga_pal[256 * 3];
-
-void keyboard_handler(int scancode, int press);
-void mouse_handler(int button, int dx, int dy, int dz,
- int drx, int dry, int drz);
-
-unsigned char reverse_byteorder(unsigned char b)
-{
- unsigned char ret = 0;
-
- for (unsigned i=0;i<8;i++){
- ret |= (b & 0x01) << (7 - i);
- b >>= 1;
- }
- return ret;
-}
-
-void create_vga_font()
-{
- memcpy(vgafont, bx_vgafont, sizeof(bx_vgafont));
-
- for (unsigned i=0;i< sizeof(bx_vgafont);i++) {
- vgafont[i] = reverse_byteorder(vgafont[i]);
- }
-}
-
-bx_svga_gui_c::bx_svga_gui_c ()
-{
- put("SVGA");
-}
-
-void bx_svga_gui_c::specific_init(
- int argc,
- char **argv,
- unsigned x_tilesize,
- unsigned y_tilesize,
- unsigned header_bar_y)
-{
- tilewidth = x_tilesize;
- tileheight = y_tilesize;
-
- if(vga_init() != 0 )
- {
- LOG_THIS setonoff(LOGLEV_PANIC, ACT_FATAL);
- BX_PANIC (("Unable to initialize SVGAlib"));
- return;
- }
-
- screen = gl_allocatecontext();
-
- dimension_update(640,400);
- create_vga_font();
- gl_setfont(8, 16, (void *)vgafont);
- gl_setwritemode(FONT_COMPRESSED);
-
- keyboard_init();
- keyboard_seteventhandler((__keyboard_handler) keyboard_handler);
-
- vga_setmousesupport(1);
- mouse_seteventhandler((__mouse_handler) mouse_handler);
- if (vga_ext_set(VGA_EXT_AVAILABLE, VGA_AVAIL_FLAGS) & VGA_CLUT8) {
- vga_ext_set(VGA_EXT_SET, VGA_CLUT8);
- clut8 = 1;
- }
- // Save settings to prepare for mode transition in set_display_mode.
- // If DISP_MODE_SIM is called first, these values will be used.
- save_vga_mode = vga_getcurrentmode();
- vga_getpalvec(0, 256, save_vga_pal);
-}
-
-void bx_svga_gui_c::text_update(
- Bit8u *old_text,
- Bit8u *new_text,
- unsigned long cursor_x,
- unsigned long cursor_y,
- bx_vga_tminfo_t tm_info,
- unsigned rows)
-{
- unsigned x, y, i;
- unsigned chars, cols;
- char s[] = " ";
- static unsigned int previ;
- unsigned int cursori;
-
- cols = res_x/fontwidth;
-
- cursori = (cursor_y*cols + cursor_x) * 2;
-
- chars = cols*rows;
-
- for (i=0; i<chars*2; i+=2) {
- if (i == cursori || i == previ || old_text[i] != new_text[i] ||
- old_text[i+1] != new_text[i+1]) {
-
- s[0] = new_text[i];
- x = (i/2) % cols;
- y = (i/2) / cols;
-
- if (i == cursori) {
- gl_setfontcolors(new_text[i+1] & 0x0F, (new_text[i+1] & 0xF0) >> 4);
- } else {
- gl_setfontcolors((new_text[i+1] & 0xF0) >> 4, new_text[i+1] & 0x0F);
- }
- gl_write(x * fontwidth, y * fontheight, s);
- }
- }
- previ = cursori;
-}
-
- int
-bx_svga_gui_c::get_clipboard_text(Bit8u **bytes, Bit32s *nbytes)
-{
- return 0;
-}
-
- int
-bx_svga_gui_c::set_clipboard_text(char *text_snapshot, Bit32u len)
-{
- return 0;
-}
-
-
-void bx_svga_gui_c::graphics_tile_update(
- Bit8u *snapshot,
- unsigned x,
- unsigned y)
-{
- gl_putbox(x, y, tilewidth, tileheight, snapshot);
-}
-
-static Bit32u vga_to_bx_key(int key)
-{
- switch (key) {
- case SCANCODE_ESCAPE: return BX_KEY_ESC;
- case SCANCODE_1: return BX_KEY_1;
- case SCANCODE_2: return BX_KEY_2;
- case SCANCODE_3: return BX_KEY_3;
- case SCANCODE_4: return BX_KEY_4;
- case SCANCODE_5: return BX_KEY_5;
- case SCANCODE_6: return BX_KEY_6;
- case SCANCODE_7: return BX_KEY_7;
- case SCANCODE_8: return BX_KEY_8;
- case SCANCODE_9: return BX_KEY_9;
- case SCANCODE_0: return BX_KEY_0;
-
- case SCANCODE_MINUS: return BX_KEY_MINUS;
- case SCANCODE_EQUAL: return BX_KEY_EQUALS;
- case SCANCODE_TAB: return BX_KEY_TAB;
- case SCANCODE_BACKSPACE: return BX_KEY_BACKSPACE;
-
- case SCANCODE_Q: return BX_KEY_Q;
- case SCANCODE_W: return BX_KEY_W;
- case SCANCODE_E: return BX_KEY_E;
- case SCANCODE_R: return BX_KEY_R;
- case SCANCODE_T: return BX_KEY_T;
- case SCANCODE_Y: return BX_KEY_Y;
- case SCANCODE_U: return BX_KEY_U;
- case SCANCODE_I: return BX_KEY_I;
- case SCANCODE_O: return BX_KEY_O;
- case SCANCODE_P: return BX_KEY_P;
-
- case SCANCODE_BRACKET_LEFT: return BX_KEY_LEFT_BRACKET;
- case SCANCODE_BRACKET_RIGHT: return BX_KEY_RIGHT_BRACKET;
-
- case SCANCODE_ENTER: return BX_KEY_ENTER;
- case SCANCODE_LEFTCONTROL: return BX_KEY_CTRL_L;
-
- case SCANCODE_A: return BX_KEY_A;
- case SCANCODE_S: return BX_KEY_S;
- case SCANCODE_D: return BX_KEY_D;
- case SCANCODE_F: return BX_KEY_F;
- case SCANCODE_G: return BX_KEY_G;
- case SCANCODE_H: return BX_KEY_H;
- case SCANCODE_J: return BX_KEY_J;
- case SCANCODE_K: return BX_KEY_K;
- case SCANCODE_L: return BX_KEY_L;
-
- case SCANCODE_SEMICOLON: return BX_KEY_SEMICOLON;
- case SCANCODE_APOSTROPHE: return BX_KEY_SINGLE_QUOTE;
- case SCANCODE_GRAVE: return BX_KEY_GRAVE;
-
- case SCANCODE_LEFTSHIFT: return BX_KEY_SHIFT_L;
- case SCANCODE_BACKSLASH: return BX_KEY_BACKSLASH;
-
- case SCANCODE_Z: return BX_KEY_Z;
- case SCANCODE_X: return BX_KEY_X;
- case SCANCODE_C: return BX_KEY_C;
- case SCANCODE_V: return BX_KEY_V;
- case SCANCODE_B: return BX_KEY_B;
- case SCANCODE_N: return BX_KEY_N;
- case SCANCODE_M: return BX_KEY_M;
-
- case SCANCODE_COMMA: return BX_KEY_COMMA;
- case SCANCODE_PERIOD: return BX_KEY_PERIOD;
- case SCANCODE_SLASH: return BX_KEY_SLASH;
-
- case SCANCODE_RIGHTSHIFT: return BX_KEY_SHIFT_R;
- case SCANCODE_KEYPADMULTIPLY: return BX_KEY_KP_MULTIPLY;
-
- case SCANCODE_LEFTALT: return BX_KEY_ALT_L;
- case SCANCODE_SPACE: return BX_KEY_SPACE;
- case SCANCODE_CAPSLOCK: return BX_KEY_CAPS_LOCK;
-
- case SCANCODE_F1: return BX_KEY_F1;
- case SCANCODE_F2: return BX_KEY_F2;
- case SCANCODE_F3: return BX_KEY_F3;
- case SCANCODE_F4: return BX_KEY_F4;
- case SCANCODE_F5: return BX_KEY_F5;
- case SCANCODE_F6: return BX_KEY_F6;
- case SCANCODE_F7: return BX_KEY_F7;
- case SCANCODE_F8: return BX_KEY_F8;
- case SCANCODE_F9: return BX_KEY_F9;
- case SCANCODE_F10: return BX_KEY_F10;
-
- case SCANCODE_NUMLOCK: return BX_KEY_NUM_LOCK;
- case SCANCODE_SCROLLLOCK: return BX_KEY_SCRL_LOCK;
-
- case SCANCODE_KEYPAD7: return BX_KEY_KP_HOME;
- case SCANCODE_KEYPAD8: return BX_KEY_KP_UP;
- case SCANCODE_KEYPAD9: return BX_KEY_KP_PAGE_UP;
- case SCANCODE_KEYPADMINUS: return BX_KEY_KP_SUBTRACT;
- case SCANCODE_KEYPAD4: return BX_KEY_KP_LEFT;
- case SCANCODE_KEYPAD5: return BX_KEY_KP_5;
- case SCANCODE_KEYPAD6: return BX_KEY_KP_RIGHT;
- case SCANCODE_KEYPADPLUS: return BX_KEY_KP_ADD;
- case SCANCODE_KEYPAD1: return BX_KEY_KP_END;
- case SCANCODE_KEYPAD2: return BX_KEY_KP_DOWN;
- case SCANCODE_KEYPAD3: return BX_KEY_KP_PAGE_DOWN;
- case SCANCODE_KEYPAD0: return BX_KEY_KP_INSERT;
-// case SCANCODE_KEYPADPERIOD: return BX_KEY_KP_; /* ??? */
-
-// case SCANCODE_LESS: return BX_KEY_KP_LESS; /* ??? */
-
- case SCANCODE_F11: return BX_KEY_F11;
- case SCANCODE_F12: return BX_KEY_F12;
-
- case SCANCODE_KEYPADENTER: return BX_KEY_KP_ENTER;
- case SCANCODE_RIGHTCONTROL: return BX_KEY_CTRL_R;
- case SCANCODE_KEYPADDIVIDE: return BX_KEY_KP_DIVIDE;
- case SCANCODE_PRINTSCREEN: return BX_KEY_PRINT;
- case SCANCODE_RIGHTALT: return BX_KEY_ALT_R;
- case SCANCODE_BREAK: return BX_KEY_PAUSE;
-
- case SCANCODE_HOME: return BX_KEY_HOME;
- case SCANCODE_CURSORBLOCKUP: return BX_KEY_UP;
- case SCANCODE_PAGEUP: return BX_KEY_PAGE_UP;
- case SCANCODE_CURSORBLOCKLEFT: return BX_KEY_LEFT;
- case SCANCODE_CURSORBLOCKRIGHT: return BX_KEY_RIGHT;
- case SCANCODE_END: return BX_KEY_END;
- case SCANCODE_CURSORBLOCKDOWN: return BX_KEY_DOWN;
- case SCANCODE_PAGEDOWN: return BX_KEY_PAGE_DOWN;
- case SCANCODE_INSERT: return BX_KEY_INSERT;
- case SCANCODE_REMOVE: return BX_KEY_DELETE;
-
- case SCANCODE_RIGHTWIN: return BX_KEY_WIN_R;
- case SCANCODE_LEFTWIN: return BX_KEY_WIN_L;
-
- default: return 0;
- }
-}
-
-void keyboard_handler(int scancode, int press)
-{
- if (scancode != SCANCODE_F12) {
- int bx_key = vga_to_bx_key(scancode);
- Bit32u key_state;
-
- if (press) {
- key_state = BX_KEY_PRESSED;
- } else {
- key_state = BX_KEY_RELEASED;
- }
-
- DEV_kbd_gen_scancode(bx_key | key_state);
- } else {
- BX_INFO(("F12 pressed"));
- // show runtime options menu, which uses stdin/stdout
- SIM->configuration_interface (NULL, CI_RUNTIME_CONFIG);
- }
-}
-
-void mouse_handler(int button, int dx, int dy, int dz,
- int drx, int dry, int drz)
-{
- int buttons = 0;
-
- if (button & MOUSE_LEFTBUTTON) {
- buttons |= 0x01;
- }
-
- if (button & MOUSE_RIGHTBUTTON) {
- buttons |= 0x02;
- }
- DEV_mouse_motion((int) (0.25 * dx), (int) -(0.25 * dy), buttons);
-}
-
-void bx_svga_gui_c::handle_events(void)
-{
- keyboard_update();
- keyboard_clearstate();
- mouse_update();
-}
-
-void bx_svga_gui_c::flush(void)
-{
- gl_copyscreen(screen);
-}
-
-void bx_svga_gui_c::clear_screen(void)
-{
- gl_clearscreen(0);
-}
-
-bx_bool bx_svga_gui_c::palette_change(
- unsigned index,
- unsigned red,
- unsigned green,
- unsigned blue)
-{
- if( index > 255 ) return 0;
-
- // without VGA_CLUT8 extension we have only 6 bits for each r,g,b value
- if (!clut8 && (red > 63 || green > 63 || blue > 63)) {
- red = red >> 2;
- green = green >> 2;
- blue = blue >> 2;
- }
-
- vga_setpalette(index, red, green, blue);
-
- return 1;
-}
-
-
-void bx_svga_gui_c::dimension_update(
- unsigned x,
- unsigned y,
- unsigned fheight,
- unsigned fwidth,
- unsigned bpp)
-{
- int newmode = 0;
-
- if (bpp > 8) {
- BX_PANIC(("%d bpp graphics mode not supported yet", bpp));
- }
- if( fheight > 0 )
- {
- fontheight = fheight;
- if (fwidth != 8) {
- x = x * 8 / fwidth;
- }
- fontwidth = 8;
- }
-
- if( (x == res_x) && (y == res_y )) return;
-
- if (x == 640 && y == 480) {
- newmode = G640x480x256;
- } else if (x == 640 && y == 400) {
- newmode = G640x400x256;
- } else if (x == 320 && y == 200) {
- newmode = G320x200x256;
- }
-
- if (!vga_hasmode(newmode)) {
- newmode = G640x480x256; // trying "default" mode...
- }
-
- if (vga_setmode(newmode) != 0)
- {
- LOG_THIS setonoff(LOGLEV_PANIC, ACT_FATAL);
- BX_PANIC (("Unable to set requested videomode: %ix%i", x, y));
- }
-
- gl_setcontextvga(newmode);
- gl_getcontext(screen);
- gl_setcontextvgavirtual(newmode);
- save_vga_mode = newmode;
-
- res_x = x;
- res_y = y;
-}
-
-
-unsigned bx_svga_gui_c::create_bitmap(
- const unsigned char *bmap,
- unsigned xdim,
- unsigned ydim)
-{
- return 0;
-}
-
-
-unsigned bx_svga_gui_c::headerbar_bitmap(
- unsigned bmap_id,
- unsigned alignment,
- void (*f)(void))
-{
- return 0;
-}
-
-
-void bx_svga_gui_c::replace_bitmap(
- unsigned hbar_id,
- unsigned bmap_id)
-{
-}
-
-
-void bx_svga_gui_c::show_headerbar(void)
-{
-}
-
-
-void bx_svga_gui_c::mouse_enabled_changed_specific (bx_bool val)
-{
-}
-
-
-void headerbar_click(int x)
-{
-}
-
-void bx_svga_gui_c::exit(void)
-{
- vga_setmode(TEXT);
- keyboard_close();
- mouse_close();
-}
-
-void
-bx_svga_gui_c::set_display_mode (disp_mode_t newmode)
-{
- // if no mode change, do nothing.
- if (disp_mode == newmode) return;
- // remember the display mode for next time
- disp_mode = newmode;
- switch (newmode) {
- case DISP_MODE_CONFIG:
- BX_DEBUG (("switch to configuration mode (back to console)"));
- // remember old values and switch to text mode
- save_vga_mode = vga_getcurrentmode();
- vga_getpalvec(0, 256, save_vga_pal);
- keyboard_close();
- vga_setmode(TEXT);
- break;
- case DISP_MODE_SIM:
- BX_DEBUG (("switch to simulation mode (fullscreen)"));
- keyboard_init();
- keyboard_seteventhandler((__keyboard_handler) keyboard_handler);
- vga_setmode(save_vga_mode);
- vga_setpalvec(0, 256, save_vga_pal);
- break;
- }
-}
-
-#endif /* if BX_WITH_SVGA */
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: term.cc,v 1.31 2003/08/17 23:40:38 cbothamy Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2000 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-
-// Define BX_PLUGGABLE in files that can be compiled into plugins. For
-// platforms that require a special tag on exported symbols, BX_PLUGGABLE
-// is used to know when we are exporting symbols and when we are importing.
-#define BX_PLUGGABLE
-
-#include "bochs.h"
-#if BX_WITH_TERM
-
-#include "icon_bochs.h"
-
-extern "C" {
-#include <curses.h>
-#include <signal.h>
-};
-
-class bx_term_gui_c : public bx_gui_c {
-public:
- bx_term_gui_c (void) {}
- DECLARE_GUI_VIRTUAL_METHODS()
-
- virtual Bit32u get_sighandler_mask ();
- // called when registered signal arrives
- virtual void sighandler (int sig);
-};
-
-// declare one instance of the gui object and call macro to insert the
-// plugin code
-static bx_term_gui_c *theGui = NULL;
-IMPLEMENT_GUI_PLUGIN_CODE(term)
-
-#define LOG_THIS theGui->
-
-bx_bool initialized = 0;
-static unsigned int text_cols = 80, text_rows = 25;
-
-static short curses_color[8] = {
- /* 0 */ COLOR_BLACK,
- /* 1 */ COLOR_BLUE,
- /* 2 */ COLOR_GREEN,
- /* 3 */ COLOR_CYAN,
- /* 4 */ COLOR_RED,
- /* 5 */ COLOR_MAGENTA,
- /* 6 */ COLOR_YELLOW,
- /* 7 */ COLOR_WHITE
-};
-
-static chtype vga_to_term[128] = {
- 0xc7, 0xfc, 0xe9, 0xe2, 0xe4, 0xe0, 0xe5, 0xe7,
- 0xea, 0xeb, 0xe8, 0xef, 0xee, 0xec, 0xc4, 0xc5,
- 0xc9, 0xe6, 0xc6, 0xf4, 0xf6, 0xf2, 0xfb, 0xf9,
- 0xff, 0xd6, 0xdc, 0xe7, 0xa3, 0xa5, ' ', ' ',
- 0xe1, 0xed, 0xf3, 0xfa, 0xf1, 0xd1, 0xaa, 0xba,
- 0xbf, ' ', 0xac, ' ', ' ', 0xa1, 0xab, 0xbb,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, ' ', ' ', ' ', ' ',
- ' ', ' ', ' ', ' ', ' ', ' ', 0xb5, ' ',
- ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
- ' ', 0xb1, ' ', ' ', ' ', ' ', 0xf7, ' ',
- 0xb0, ' ', ' ', ' ', ' ', 0xb2, ' ', ' '
-};
-
-static void
-do_scan(int key_event, int shift, int ctrl, int alt)
-{
- /* XXX At some point, cache alt/ctrl/shift so only when the state
- changes do we simulate a press or release, to cut down on
- keyboard input to the simulated machine */
-
- BX_DEBUG(("key_event %d/0x%x %s%s%s",
- key_event,key_event,
- shift?"(shift)":"",
- ctrl?"(ctrl)":"",
- alt?"(alt)":""));
- if(shift)
- DEV_kbd_gen_scancode(BX_KEY_SHIFT_L);
- if(ctrl)
- DEV_kbd_gen_scancode(BX_KEY_CTRL_L);
- if(alt)
- DEV_kbd_gen_scancode(BX_KEY_ALT_L);
- DEV_kbd_gen_scancode(key_event);
- key_event |= BX_KEY_RELEASED;
-
- DEV_kbd_gen_scancode(key_event);
- if(alt)
- DEV_kbd_gen_scancode(BX_KEY_ALT_L|BX_KEY_RELEASED);
- if(ctrl)
- DEV_kbd_gen_scancode(BX_KEY_CTRL_L|BX_KEY_RELEASED);
- if(shift)
- DEV_kbd_gen_scancode(BX_KEY_SHIFT_L|BX_KEY_RELEASED);
-}
-
-Bit32u
-bx_term_gui_c::get_sighandler_mask ()
-{
- return
- (1<<SIGHUP)
- | (1<<SIGINT)
- | (1<<SIGQUIT)
-#ifdef SIGSTOP
- | (1<<SIGSTOP)
-#endif
-#ifdef SIGTSTP
- | (1<<SIGTSTP)
-#endif
- | (1<<SIGTERM);
-}
-
-void
-bx_term_gui_c::sighandler(int signo)
-{
- switch(signo) {
- case SIGINT:
- do_scan(BX_KEY_C,0,1,0);
- break;
-#ifdef SIGSTOP
- case SIGSTOP:
- do_scan(BX_KEY_S,0,1,0);
- break;
-#endif
-#ifdef SIGTSTP
- case SIGTSTP:
- do_scan(BX_KEY_Z,0,1,0);
- break;
-#endif
- default:
- BX_INFO(("sig %d caught",signo));
- break;
- }
-}
-
-// ::SPECIFIC_INIT()
-//
-// Called from gui.cc, once upon program startup, to allow for the
-// specific GUI code (X11, BeOS, ...) to be initialized.
-//
-// argc, argv: not used right now, but the intention is to pass native GUI
-// specific options from the command line. (X11 options, BeOS options,...)
-//
-// tilewidth, tileheight: for optimization, graphics_tile_update() passes
-// only updated regions of the screen to the gui code to be redrawn.
-// These define the dimensions of a region (tile).
-// headerbar_y: A headerbar (toolbar) is display on the top of the
-// VGA window, showing floppy status, and other information. It
-// always assumes the width of the current VGA mode width, but
-// it's height is defined by this parameter.
-
- void
-bx_term_gui_c::specific_init(int argc, char **argv, unsigned tilewidth, unsigned tileheight,
- unsigned headerbar_y)
-{
- put("TGUI");
- UNUSED(argc);
- UNUSED(argv);
- UNUSED(tilewidth);
- UNUSED(tileheight);
- UNUSED(headerbar_y);
-
- UNUSED(bochs_icon_bits); // global variable
-
- // the ask menu causes trouble
- io->set_log_action(LOGLEV_PANIC, ACT_FATAL);
- // logfile should be different from stderr, otherwise terminal mode
- // really ends up having fun
- if (!strcmp(bx_options.log.Ofilename->getptr(), "-"))
- BX_PANIC(("cannot log to stderr in term mode"));
-
- initscr();
- start_color();
- cbreak();
- curs_set(2);
- keypad(stdscr,TRUE);
- nodelay(stdscr, TRUE);
- noecho();
-
-#if BX_HAVE_COLOR_SET
- if (has_colors()) {
- for (int i=0; i<COLORS; i++) {
- for (int j=0; j<COLORS; j++) {
- if ((i!=0)||(j!=0)) init_pair(i * COLORS + j, j, i);
- }
- }
- }
-#endif
-
- if (bx_options.Oprivate_colormap->get ())
- BX_ERROR(("WARNING: private_colormap option ignored."));
- initialized = 1;
-}
-
-
-
-void
-do_char(int character,int alt)
-{
- switch (character) {
- // control keys
- case 0x9: do_scan(BX_KEY_TAB,0,0,alt); break;
- case 0xa: do_scan(BX_KEY_KP_ENTER,0,0,alt); break;
- case 0xd: do_scan(BX_KEY_KP_DELETE,0,0,alt); break;
- case 0x1: do_scan(BX_KEY_A,0,1,alt); break;
- case 0x2: do_scan(BX_KEY_B,0,1,alt); break;
- case 0x3: do_scan(BX_KEY_C,0,1,alt); break;
- case 0x4: do_scan(BX_KEY_D,0,1,alt); break;
- case 0x5: do_scan(BX_KEY_E,0,1,alt); break;
- case 0x6: do_scan(BX_KEY_F,0,1,alt); break;
- case 0x7: do_scan(BX_KEY_G,0,1,alt); break;
- case 0x8: do_scan(BX_KEY_H,0,1,alt); break;
- case 0xb: do_scan(BX_KEY_K,0,1,alt); break;
- case 0xc: do_scan(BX_KEY_L,0,1,alt); break;
- case 0xe: do_scan(BX_KEY_N,0,1,alt); break;
- case 0xf: do_scan(BX_KEY_O,0,1,alt); break;
- case 0x10: do_scan(BX_KEY_P,0,1,alt); break;
- case 0x11: do_scan(BX_KEY_Q,0,1,alt); break;
- case 0x12: do_scan(BX_KEY_R,0,1,alt); break;
- case 0x13: do_scan(BX_KEY_S,0,1,alt); break;
- case 0x14: do_scan(BX_KEY_T,0,1,alt); break;
- case 0x15: do_scan(BX_KEY_U,0,1,alt); break;
- case 0x16: do_scan(BX_KEY_V,0,1,alt); break;
- case 0x17: do_scan(BX_KEY_W,0,1,alt); break;
- case 0x18: do_scan(BX_KEY_X,0,1,alt); break;
- case 0x19: do_scan(BX_KEY_Y,0,1,alt); break;
- case 0x1a: do_scan(BX_KEY_Z,0,1,alt); break;
- case 0x20: do_scan(BX_KEY_SPACE,0,0,alt); break;
- case 0x107: do_scan(BX_KEY_BACKSPACE,0,0,alt); break;
- case 0x102: do_scan(BX_KEY_DOWN,0,0,alt); break;
- case 0x103: do_scan(BX_KEY_UP,0,0,alt); break;
- case 0x104: do_scan(BX_KEY_LEFT,0,0,alt); break;
- case 0x105: do_scan(BX_KEY_RIGHT,0,0,alt); break;
- case 0x152: do_scan(BX_KEY_PAGE_DOWN,0,0,alt); break;
- case 0x153: do_scan(BX_KEY_PAGE_UP,0,0,alt); break;
- case 0x106: do_scan(BX_KEY_HOME,0,0,alt); break;
- case 0x168: do_scan(BX_KEY_END,0,0,alt); break;
- case 0x14b: do_scan(BX_KEY_INSERT,0,0,alt); break;
- case 0x7f: do_scan(BX_KEY_DELETE,0,0,alt); break;
- case 0x1b: do_scan(BX_KEY_ESC,0,0,alt); break;
- case '!': do_scan(BX_KEY_1,1,0,alt); break;
- case '\'': do_scan(BX_KEY_SINGLE_QUOTE,0,0,alt); break;
- case '#': do_scan(BX_KEY_3,1,0,alt); break;
- case '$': do_scan(BX_KEY_4,1,0,alt); break;
- case '%': do_scan(BX_KEY_5,1,0,alt); break;
- case '^': do_scan(BX_KEY_6,1,0,alt); break;
- case '&': do_scan(BX_KEY_7,1,0,alt); break;
- case '"': do_scan(BX_KEY_SINGLE_QUOTE,1,0,alt); break;
-
- // ()*+,-./
- case '(': do_scan(BX_KEY_9,1,0,alt); break;
- case ')': do_scan(BX_KEY_0,1,0,alt); break;
- case '*': do_scan(BX_KEY_8,1,0,alt); break;
- case '+': do_scan(BX_KEY_EQUALS,1,0,alt); break;
- case ',': do_scan(BX_KEY_COMMA,0,0,alt); break;
- case '-': do_scan(BX_KEY_MINUS,0,0,alt); break;
- case '.': do_scan(BX_KEY_PERIOD,0,0,alt); break;
- case '/': do_scan(BX_KEY_SLASH,0,0,alt); break;
-
- // 01234567
- case '0': do_scan(BX_KEY_0,0,0,alt); break;
- case '1': do_scan(BX_KEY_1,0,0,alt); break;
- case '2': do_scan(BX_KEY_2,0,0,alt); break;
- case '3': do_scan(BX_KEY_3,0,0,alt); break;
- case '4': do_scan(BX_KEY_4,0,0,alt); break;
- case '5': do_scan(BX_KEY_5,0,0,alt); break;
- case '6': do_scan(BX_KEY_6,0,0,alt); break;
- case '7': do_scan(BX_KEY_7,0,0,alt); break;
-
- // 89:;<=>?
- case '8': do_scan(BX_KEY_8,0,0,alt); break;
- case '9': do_scan(BX_KEY_9,0,0,alt); break;
- case ':': do_scan(BX_KEY_SEMICOLON,1,0,alt); break;
- case ';': do_scan(BX_KEY_SEMICOLON,0,0,alt); break;
- case '<': do_scan(BX_KEY_COMMA,1,0,alt); break;
- case '=': do_scan(BX_KEY_EQUALS,0,0,alt); break;
- case '>': do_scan(BX_KEY_PERIOD,1,0,alt); break;
- case '?': do_scan(BX_KEY_SLASH,1,0,alt); break;
-
- // @ABCDEFG
- case '@': do_scan(BX_KEY_2,1,0,alt); break;
- case 'A': do_scan(BX_KEY_A,1,0,alt); break;
- case 'B': do_scan(BX_KEY_B,1,0,alt); break;
- case 'C': do_scan(BX_KEY_C,1,0,alt); break;
- case 'D': do_scan(BX_KEY_D,1,0,alt); break;
- case 'E': do_scan(BX_KEY_E,1,0,alt); break;
- case 'F': do_scan(BX_KEY_F,1,0,alt); break;
- case 'G': do_scan(BX_KEY_G,1,0,alt); break;
-
-
- // HIJKLMNO
- case 'H': do_scan(BX_KEY_H,1,0,alt); break;
- case 'I': do_scan(BX_KEY_I,1,0,alt); break;
- case 'J': do_scan(BX_KEY_J,1,0,alt); break;
- case 'K': do_scan(BX_KEY_K,1,0,alt); break;
- case 'L': do_scan(BX_KEY_L,1,0,alt); break;
- case 'M': do_scan(BX_KEY_M,1,0,alt); break;
- case 'N': do_scan(BX_KEY_N,1,0,alt); break;
- case 'O': do_scan(BX_KEY_O,1,0,alt); break;
-
-
- // PQRSTUVW
- case 'P': do_scan(BX_KEY_P,1,0,alt); break;
- case 'Q': do_scan(BX_KEY_Q,1,0,alt); break;
- case 'R': do_scan(BX_KEY_R,1,0,alt); break;
- case 'S': do_scan(BX_KEY_S,1,0,alt); break;
- case 'T': do_scan(BX_KEY_T,1,0,alt); break;
- case 'U': do_scan(BX_KEY_U,1,0,alt); break;
- case 'V': do_scan(BX_KEY_V,1,0,alt); break;
- case 'W': do_scan(BX_KEY_W,1,0,alt); break;
-
- // XYZ[\]^_
- case 'X': do_scan(BX_KEY_X,1,0,alt); break;
- case 'Y': do_scan(BX_KEY_Y,1,0,alt); break;
- case 'Z': do_scan(BX_KEY_Z,1,0,alt); break;
- case '{': do_scan(BX_KEY_LEFT_BRACKET,1,0,alt); break;
- case '|': do_scan(BX_KEY_BACKSLASH,1,0,alt); break;
- case '}': do_scan(BX_KEY_RIGHT_BRACKET,1,0,alt); break;
- case '_': do_scan(BX_KEY_MINUS,1,0,alt); break;
-
- // `abcdefg
- case '`': do_scan(BX_KEY_GRAVE,0,0,alt); break;
- case 'a': do_scan(BX_KEY_A,0,0,alt); break;
- case 'b': do_scan(BX_KEY_B,0,0,alt); break;
- case 'c': do_scan(BX_KEY_C,0,0,alt); break;
- case 'd': do_scan(BX_KEY_D,0,0,alt); break;
- case 'e': do_scan(BX_KEY_E,0,0,alt); break;
- case 'f': do_scan(BX_KEY_F,0,0,alt); break;
- case 'g': do_scan(BX_KEY_G,0,0,alt); break;
-
- // hijklmno
- case 'h': do_scan(BX_KEY_H,0,0,alt); break;
- case 'i': do_scan(BX_KEY_I,0,0,alt); break;
- case 'j': do_scan(BX_KEY_J,0,0,alt); break;
- case 'k': do_scan(BX_KEY_K,0,0,alt); break;
- case 'l': do_scan(BX_KEY_L,0,0,alt); break;
- case 'm': do_scan(BX_KEY_M,0,0,alt); break;
- case 'n': do_scan(BX_KEY_N,0,0,alt); break;
- case 'o': do_scan(BX_KEY_O,0,0,alt); break;
-
- // pqrstuvw
- case 'p': do_scan(BX_KEY_P,0,0,alt); break;
- case 'q': do_scan(BX_KEY_Q,0,0,alt); break;
- case 'r': do_scan(BX_KEY_R,0,0,alt); break;
- case 's': do_scan(BX_KEY_S,0,0,alt); break;
- case 't': do_scan(BX_KEY_T,0,0,alt); break;
- case 'u': do_scan(BX_KEY_U,0,0,alt); break;
- case 'v': do_scan(BX_KEY_V,0,0,alt); break;
- case 'w': do_scan(BX_KEY_W,0,0,alt); break;
-
- // xyz{|}~
- case 'x': do_scan(BX_KEY_X,0,0,alt); break;
- case 'y': do_scan(BX_KEY_Y,0,0,alt); break;
- case 'z': do_scan(BX_KEY_Z,0,0,alt); break;
- case '[': do_scan(BX_KEY_LEFT_BRACKET,0,0,alt); break;
- case '\\': do_scan(BX_KEY_BACKSLASH,0,0,alt); break;
- case ']': do_scan(BX_KEY_RIGHT_BRACKET,0,0,alt); break;
- case '~': do_scan(BX_KEY_GRAVE,1,0,alt); break;
-
- // function keys
- case KEY_F(1): do_scan(BX_KEY_F1,0,0,alt); break;
- case KEY_F(2): do_scan(BX_KEY_F2,0,0,alt); break;
- case KEY_F(3): do_scan(BX_KEY_F3,0,0,alt); break;
- case KEY_F(4): do_scan(BX_KEY_F4,0,0,alt); break;
- case KEY_F(5): do_scan(BX_KEY_F5,0,0,alt); break;
- case KEY_F(6): do_scan(BX_KEY_F6,0,0,alt); break;
- case KEY_F(7): do_scan(BX_KEY_F7,0,0,alt); break;
- case KEY_F(8): do_scan(BX_KEY_F8,0,0,alt); break;
- case KEY_F(9): do_scan(BX_KEY_F9,0,0,alt); break;
- case KEY_F(10): do_scan(BX_KEY_F10,0,0,alt); break;
- case KEY_F(11): do_scan(BX_KEY_F11,0,0,alt); break;
- case KEY_F(12): do_scan(BX_KEY_F12,0,0,alt); break;
-
- // shifted function keys
- case KEY_F(13): do_scan(BX_KEY_F1,1,0,alt); break;
- case KEY_F(14): do_scan(BX_KEY_F2,1,0,alt); break;
- case KEY_F(15): do_scan(BX_KEY_F3,1,0,alt); break;
- case KEY_F(16): do_scan(BX_KEY_F4,1,0,alt); break;
- case KEY_F(17): do_scan(BX_KEY_F5,1,0,alt); break;
- case KEY_F(18): do_scan(BX_KEY_F6,1,0,alt); break;
- case KEY_F(19): do_scan(BX_KEY_F7,1,0,alt); break;
- case KEY_F(20): do_scan(BX_KEY_F8,1,0,alt); break;
-
- default:
- if(character > 0x79) {
- do_char(character - 0x80,1);
- break;
- }
-
- BX_INFO(("character unhandled: 0x%x",character));
- break;
- }
-}
-
-
-// ::HANDLE_EVENTS()
-//
-// Called periodically (vga_update_interval in .bochsrc) so the
-// the gui code can poll for keyboard, mouse, and other
-// relevant events.
-
- void
-bx_term_gui_c::handle_events(void)
-{
- int character;
- while((character = getch()) != ERR) {
- BX_DEBUG(("scancode(0x%x)",character));
- do_char(character,0);
- }
-}
-
-
-
-// ::FLUSH()
-//
-// Called periodically, requesting that the gui code flush all pending
-// screen update requests.
-
- void
-bx_term_gui_c::flush(void)
-{
- if (initialized)
- refresh();
-}
-
-
-// ::CLEAR_SCREEN()
-//
-// Called to request that the VGA region is cleared. Don't
-// clear the area that defines the headerbar.
-
- void
-bx_term_gui_c::clear_screen(void)
-{
- clear();
-#if BX_HAVE_COLOR_SET
- color_set(7, NULL);
-#endif
-#if BX_HAVE_MVHLINE
- if (LINES > (int)text_rows) {
- mvhline(text_rows, 0, ACS_HLINE, text_cols);
- }
-#endif
-#if BX_HAVE_MVVLINE
- if (COLS > (int)text_cols) {
- mvvline(0, text_cols, ACS_VLINE, text_rows);
- }
-#endif
- if ((LINES > (int)text_rows) && (COLS > (int)text_cols)) {
- mvaddch(text_rows, text_cols, ACS_LRCORNER);
- }
-}
-
-int
-get_color_pair(Bit8u vga_attr)
-{
- int term_attr;
-
- term_attr = curses_color[vga_attr & 0x07];
- term_attr |= (curses_color[(vga_attr & 0x70) >> 4] << 3);
- return term_attr;
-}
-
-chtype
-get_term_char(Bit8u vga_char[])
-{
- int term_char;
-
- if ((vga_char[1] & 0x0f) == ((vga_char[1] >> 4) & 0x0f)) {
- return ' ';
- }
- switch (vga_char[0]) {
- case 0x04: term_char = ACS_DIAMOND; break;
- case 0x18: term_char = ACS_UARROW; break;
- case 0x19: term_char = ACS_DARROW; break;
- case 0x1a: term_char = ACS_RARROW; break;
- case 0x1b: term_char = ACS_LARROW; break;
- case 0xc4:
- case 0xcd: term_char = ACS_HLINE; break;
- case 0xb3:
- case 0xba: term_char = ACS_VLINE; break;
- case 0xc9:
- case 0xd5:
- case 0xd6:
- case 0xda: term_char = ACS_ULCORNER; break;
- case 0xb7:
- case 0xb8:
- case 0xbb:
- case 0xbf: term_char = ACS_URCORNER; break;
- case 0xc0:
- case 0xc8:
- case 0xd3:
- case 0xd4: term_char = ACS_LLCORNER; break;
- case 0xbc:
- case 0xbd:
- case 0xbe:
- case 0xd9: term_char = ACS_LRCORNER; break;
- case 0xc3:
- case 0xc6:
- case 0xc7:
- case 0xcc: term_char = ACS_LTEE; break;
- case 0xb4:
- case 0xb5:
- case 0xb6:
- case 0xb9: term_char = ACS_RTEE; break;
- case 0xc2:
- case 0xcb:
- case 0xd1:
- case 0xd2: term_char = ACS_TTEE; break;
- case 0xc1:
- case 0xca:
- case 0xcf:
- case 0xd0: term_char = ACS_BTEE; break;
- case 0xc5:
- case 0xce:
- case 0xd7:
- case 0xd8: term_char = ACS_PLUS; break;
- case 0xb0:
- case 0xb1: term_char = ACS_CKBOARD; break;
- case 0xb2: term_char = ACS_BOARD; break;
- case 0xdb: term_char = ACS_BLOCK; break;
- default:
- if (vga_char[0] > 0x7f) {
- term_char = vga_to_term[vga_char[0]-0x80];
- } else if (vga_char[0] > 0x1f) {
- term_char = vga_char[0];
- } else {
- term_char = ' ';
- }
- }
- return term_char;
-}
-
-// ::TEXT_UPDATE()
-//
-// Called in a VGA text mode, to update the screen with
-// new content.
-//
-// old_text: array of character/attributes making up the contents
-// of the screen from the last call. See below
-// new_text: array of character/attributes making up the current
-// contents, which should now be displayed. See below
-//
-// format of old_text & new_text: each is 4000 bytes long.
-// This represents 80 characters wide by 25 high, with
-// each character being 2 bytes. The first by is the
-// character value, the second is the attribute byte.
-// I currently don't handle the attribute byte.
-//
-// cursor_x: new x location of cursor
-// cursor_y: new y location of cursor
-
- void
-bx_term_gui_c::text_update(Bit8u *old_text, Bit8u *new_text,
- unsigned long cursor_x, unsigned long cursor_y,
- bx_vga_tminfo_t tm_info, unsigned nrows)
-{
- unsigned char *old_line, *new_line, *new_start;
- unsigned char cAttr;
- unsigned int hchars, rows, x, y;
- chtype ch;
- bx_bool force_update = 0;
-
- UNUSED(nrows);
-
- if(charmap_updated) {
- force_update = 1;
- charmap_updated = 0;
- }
-
- new_start = new_text;
- rows = text_rows;
- y = 0;
- do {
- hchars = text_cols;
- new_line = new_text;
- old_line = old_text;
- x = 0;
- do {
- if (force_update || (old_text[0] != new_text[0])
- || (old_text[1] != new_text[1])) {
-#if BX_HAVE_COLOR_SET
- if (has_colors()) {
- color_set(get_color_pair(new_text[1]), NULL);
- }
-#endif
- ch = get_term_char(&new_text[0]);
- if ((new_text[1] & 0x08) > 0) ch |= A_BOLD;
- if ((new_text[1] & 0x80) > 0) ch |= A_BLINK;
- mvaddch(y, x, ch);
- }
- x++;
- new_text+=2;
- old_text+=2;
- } while (--hchars);
- y++;
- new_text = new_line + tm_info.line_offset;
- old_text = old_line + tm_info.line_offset;
- } while (--rows);
-
- if ((cursor_x<text_cols) && (cursor_y<text_rows)
- && (tm_info.cs_start <= tm_info.cs_end)) {
- if(cursor_x>0)
- cursor_x--;
- else {
- cursor_x=COLS-1;
- cursor_y--;
- }
- cAttr = new_start[cursor_y*tm_info.line_offset+cursor_x*2+1];
-#if BX_HAVE_COLOR_SET
- if (has_colors()) {
- color_set(get_color_pair(cAttr), NULL);
- }
-#endif
- ch = get_term_char(&new_start[cursor_y*tm_info.line_offset+cursor_x*2]);
- if ((cAttr & 0x08) > 0) ch |= A_BOLD;
- if ((cAttr & 0x80) > 0) ch |= A_REVERSE;
- mvaddch(cursor_y, cursor_x, ch);
- curs_set(2);
- } else {
- curs_set(0);
- }
-}
-
- int
-bx_term_gui_c::get_clipboard_text(Bit8u **bytes, Bit32s *nbytes)
-{
- return 0;
-}
-
- int
-bx_term_gui_c::set_clipboard_text(char *text_snapshot, Bit32u len)
-{
- return 0;
-}
-
-
-// ::PALETTE_CHANGE()
-//
-// Allocate a color in the native GUI, for this color, and put
-// it in the colormap location 'index'.
-// returns: 0=no screen update needed (color map change has direct effect)
-// 1=screen updated needed (redraw using current colormap)
-
- bx_bool
-bx_term_gui_c::palette_change(unsigned index, unsigned red, unsigned green, unsigned blue)
-{
- BX_DEBUG(("color pallete request (%d,%d,%d,%d) ignored",
- index,red,green,blue));
- return(0);
-}
-
-
-// ::GRAPHICS_TILE_UPDATE()
-//
-// Called to request that a tile of graphics be drawn to the
-// screen, since info in this region has changed.
-//
-// tile: array of 8bit values representing a block of pixels with
-// dimension equal to the 'tilewidth' & 'tileheight' parameters to
-// ::specific_init(). Each value specifies an index into the
-// array of colors you allocated for ::palette_change()
-// x0: x origin of tile
-// y0: y origin of tile
-//
-// note: origin of tile and of window based on (0,0) being in the upper
-// left of the window.
-
- void
-bx_term_gui_c::graphics_tile_update(Bit8u *tile, unsigned x0, unsigned y0)
-{
- UNUSED(tile);
- UNUSED(x0);
- UNUSED(y0);
-}
-
-
-
-// ::DIMENSION_UPDATE()
-//
-// Called when the VGA mode changes it's X,Y dimensions.
-// Resize the window to this size, but you need to add on
-// the height of the headerbar to the Y value.
-//
-// x: new VGA x size
-// y: new VGA y size (add headerbar_y parameter from ::specific_init().
-// fheight: new VGA character height in text mode
-// fwidth : new VGA character width in text mode
-// bpp : bits per pixel in graphics mode
-
- void
-bx_term_gui_c::dimension_update(unsigned x, unsigned y, unsigned fheight, unsigned fwidth, unsigned bpp)
-{
- if (bpp > 8) {
- BX_PANIC(("%d bpp graphics mode not supported", bpp));
- }
- if (fheight > 0) {
- text_cols = x / fwidth;
- text_rows = y / fheight;
-#if BX_HAVE_COLOR_SET
- color_set(7, NULL);
-#endif
-#if BX_HAVE_MVHLINE
- if (LINES > (int)text_rows) {
- mvhline(text_rows, 0, ACS_HLINE, text_cols);
- }
-#endif
-#if BX_HAVE_MVVLINE
- if (COLS > (int)text_cols) {
- mvvline(0, text_cols, ACS_VLINE, text_rows);
- }
-#endif
- if ((LINES > (int)text_rows) && (COLS > (int)text_cols)) {
- mvaddch(text_rows, text_cols, ACS_LRCORNER);
- }
- }
-}
-
-
-// ::CREATE_BITMAP()
-//
-// Create a monochrome bitmap of size 'xdim' by 'ydim', which will
-// be drawn in the headerbar. Return an integer ID to the bitmap,
-// with which the bitmap can be referenced later.
-//
-// bmap: packed 8 pixels-per-byte bitmap. The pixel order is:
-// bit0 is the left most pixel, bit7 is the right most pixel.
-// xdim: x dimension of bitmap
-// ydim: y dimension of bitmap
-
- unsigned
-bx_term_gui_c::create_bitmap(const unsigned char *bmap, unsigned xdim, unsigned ydim)
-{
- UNUSED(bmap);
- UNUSED(xdim);
- UNUSED(ydim);
- return(0);
-}
-
-
-// ::HEADERBAR_BITMAP()
-//
-// Called to install a bitmap in the bochs headerbar (toolbar).
-//
-// bmap_id: will correspond to an ID returned from
-// ::create_bitmap(). 'alignment' is either BX_GRAVITY_LEFT
-// or BX_GRAVITY_RIGHT, meaning install the bitmap in the next
-// available leftmost or rightmost space.
-// alignment: is either BX_GRAVITY_LEFT or BX_GRAVITY_RIGHT,
-// meaning install the bitmap in the next
-// available leftmost or rightmost space.
-// f: a 'C' function pointer to callback when the mouse is clicked in
-// the boundaries of this bitmap.
-
- unsigned
-bx_term_gui_c::headerbar_bitmap(unsigned bmap_id, unsigned alignment, void (*f)(void))
-{
- UNUSED(bmap_id);
- UNUSED(alignment);
- UNUSED(f);
- return(0);
-}
-
-
-// ::SHOW_HEADERBAR()
-//
-// Show (redraw) the current headerbar, which is composed of
-// currently installed bitmaps.
-
- void
-bx_term_gui_c::show_headerbar(void)
-{
-}
-
-
-// ::REPLACE_BITMAP()
-//
-// Replace the bitmap installed in the headerbar ID slot 'hbar_id',
-// with the one specified by 'bmap_id'. 'bmap_id' will have
-// been generated by ::create_bitmap(). The old and new bitmap
-// must be of the same size. This allows the bitmap the user
-// sees to change, when some action occurs. For example when
-// the user presses on the floppy icon, it then displays
-// the ejected status.
-//
-// hbar_id: headerbar slot ID
-// bmap_id: bitmap ID
-
- void
-bx_term_gui_c::replace_bitmap(unsigned hbar_id, unsigned bmap_id)
-{
- UNUSED(hbar_id);
- UNUSED(bmap_id);
-}
-
-
-// ::EXIT()
-//
-// Called before bochs terminates, to allow for a graceful
-// exit from the native GUI mechanism.
-
- void
-bx_term_gui_c::exit(void)
-{
- if (!initialized) return;
- clear();
- flush();
- endwin();
- BX_DEBUG(("exiting"));
-}
-
- void
-bx_term_gui_c::mouse_enabled_changed_specific (bx_bool val)
-{
-}
-#endif /* if BX_WITH_TERM */
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: textconfig.cc,v 1.18 2003/10/24 15:39:57 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// This is code for a text-mode configuration interface. Note that this file
-// does NOT include bochs.h. Instead, it does all of its contact with
-// the simulator through an object called SIM, defined in siminterface.cc
-// and siminterface.h. This separation adds an extra layer of method
-// calls before any work can be done, but the benefit is that the compiler
-// enforces the rules. I can guarantee that textconfig.cc doesn't call any
-// I/O device objects directly, for example, because the bx_devices symbol
-// isn't even defined in this context.
-//
-
-#include "config.h"
-
-extern "C" {
-#include <stdio.h>
-#include <ctype.h>
-#include <string.h>
-#include <assert.h>
-}
-#include "osdep.h"
-#include "textconfig.h"
-#include "siminterface.h"
-#include "extplugin.h"
-#ifdef WIN32
-#include "win32dialog.h"
-#endif
-
-#define CI_PATH_LENGTH 512
-
-#define BX_INSERTED 11
-
-/* functions for changing particular options */
-void bx_config_interface_init ();
-int bx_read_rc (char *rc);
-int bx_write_rc (char *rc);
-void bx_log_options (int individual);
-
-/******************************************************************/
-/* lots of code stolen from bximage.c */
-/* remove leading spaces, newline junk at end. returns pointer to
- cleaned string, which is between s0 and the null */
-char *
-clean_string (char *s0)
-{
- char *s = s0;
- char *ptr;
- /* find first nonblank */
- while (isspace (*s))
- s++;
- /* truncate string at first non-alphanumeric */
- ptr = s;
- while (isprint (*ptr))
- ptr++;
- *ptr = 0;
- return s;
-}
-
-void
-double_percent (char *s, int max_len)
-{
- char d[CI_PATH_LENGTH];
- int i=0,j=0;
-
- if (max_len>CI_PATH_LENGTH)
- max_len=CI_PATH_LENGTH;
-
- max_len--;
-
- while((s[i]!=0)&&(j<max_len))
- {
- d[j++]=s[i];
- if((s[i]=='%')&&(j<max_len))
- {
- d[j++]=s[i];
- }
- i++;
- }
- d[j]=0;
- strcpy(s,d);
-}
-
-/* returns 0 on success, -1 on failure. The value goes into out. */
-int
-ask_uint (char *prompt, Bit32u min, Bit32u max, Bit32u the_default, Bit32u *out, int base)
-{
- Bit32u n = max + 1;
- char buffer[1024];
- char *clean;
- int illegal;
- assert (base==10 || base==16);
- while (1) {
- printf (prompt, the_default);
- if (!fgets (buffer, sizeof(buffer), stdin))
- return -1;
- clean = clean_string (buffer);
- if (strlen(clean) < 1) {
- // empty line, use the default
- *out = the_default;
- return 0;
- }
- const char *format = (base==10) ? "%d" : "%x";
- illegal = (1 != sscanf (buffer, format, &n));
- if (illegal || n<min || n>max) {
- printf ("Your choice (%s) was not an integer between %u and %u.\n\n",
- clean, min, max);
- } else {
- // choice is okay
- *out = n;
- return 0;
- }
- }
-}
-
-// identical to ask_uint, but uses signed comparisons
-int
-ask_int (char *prompt, Bit32s min, Bit32s max, Bit32s the_default, Bit32s *out)
-{
- int n = max + 1;
- char buffer[1024];
- char *clean;
- int illegal;
- while (1) {
- printf (prompt, the_default);
- if (!fgets (buffer, sizeof(buffer), stdin))
- return -1;
- clean = clean_string (buffer);
- if (strlen(clean) < 1) {
- // empty line, use the default
- *out = the_default;
- return 0;
- }
- illegal = (1 != sscanf (buffer, "%d", &n));
- if (illegal || n<min || n>max) {
- printf ("Your choice (%s) was not an integer between %d and %d.\n\n",
- clean, min, max);
- } else {
- // choice is okay
- *out = n;
- return 0;
- }
- }
-}
-
-int
-ask_menu (char *prompt, int n_choices, char *choice[], int the_default, int *out)
-{
- char buffer[1024];
- char *clean;
- int i;
- *out = -1;
- while (1) {
- printf (prompt, choice[the_default]);
- if (!fgets (buffer, sizeof(buffer), stdin))
- return -1;
- clean = clean_string (buffer);
- if (strlen(clean) < 1) {
- // empty line, use the default
- *out = the_default;
- return 0;
- }
- for (i=0; i<n_choices; i++) {
- if (!strcmp (choice[i], clean)) {
- // matched, return the choice number
- *out = i;
- return 0;
- }
- }
- if (clean[0] != '?')
- printf ("Your choice (%s) did not match any of the choices:\n", clean);
- for (i=0; i<n_choices; i++) {
- if (i>0) printf (", ");
- printf ("%s", choice[i]);
- }
- printf ("\n");
- }
-}
-
-int
-ask_yn (char *prompt, Bit32u the_default, Bit32u *out)
-{
- char buffer[16];
- char *clean;
- *out = 1<<31;
- while (1) {
- // if there's a %s field, substitute in the default yes/no.
- printf (prompt, the_default ? "yes" : "no");
- if (!fgets (buffer, sizeof(buffer), stdin))
- return -1;
- clean = clean_string (buffer);
- if (strlen(clean) < 1) {
- // empty line, use the default
- *out = the_default;
- return 0;
- }
- switch (tolower(clean[0])) {
- case 'y': *out=1; return 0;
- case 'n': *out=0; return 0;
- }
- printf ("Please type either yes or no.\n");
- }
-}
-
-// returns -1 on error (stream closed or something)
-// returns 0 if default was taken
-// returns 1 if value changed
-int
-ask_string (char *prompt, char *the_default, char *out)
-{
- char buffer[1024];
- char *clean;
- assert (the_default != out);
- out[0] = 0;
- printf (prompt, the_default);
- if (fgets (buffer, sizeof(buffer), stdin) == NULL)
- return -1;
- clean = clean_string (buffer);
- if (strlen(clean) < 1) {
- // empty line, use the default
- strcpy (out, the_default);
- return 0;
- }
- strcpy (out, clean);
- return 1;
-}
-
-/******************************************************************/
-
-static char *startup_menu_prompt =
-"------------------------------\n"
-"Bochs Configuration: Main Menu\n"
-"------------------------------\n"
-"\n"
-"This is the Bochs Configuration Interface, where you can describe the\n"
-"machine that you want to simulate. Bochs has already searched for a\n"
-"configuration file (typically called bochsrc.txt) and loaded it if it\n"
-"could be found. When you are satisfied with the configuration, go\n"
-"ahead and start the simulation.\n"
-"\n"
-"You can also start bochs with the -q option to skip these menus.\n"
-"\n"
-"1. Restore factory default configuration\n"
-"2. Read options from...\n"
-"3. Edit options\n"
-"4. Save options to...\n"
-"5. Begin simulation\n"
-"6. Quit now\n"
-"\n"
-"Please choose one: [%d] ";
-
-static char *startup_options_prompt =
-"------------------\n"
-"Bochs Options Menu\n"
-"------------------\n"
-"0. Return to previous menu\n"
-"1. Log file: %s\n"
-"2. Log prefix: %s\n"
-"3. Debug log file: %s\n"
-"4. Log options for all devices\n"
-"5. Log options for individual devices\n"
-"6. Memory options\n"
-"7. Interface options\n"
-"8. Disk options\n"
-"9. Serial or Parallel port options\n"
-"10. Sound Blaster 16 options\n"
-"11. NE2000 network card options\n"
-"12. Keyboard options\n"
-"13. Other options\n"
-"\n"
-"Please choose one: [0] ";
-
-static char *runtime_menu_prompt =
-"---------------------\n"
-"Bochs Runtime Options\n"
-"---------------------\n"
-"1. Floppy disk 0: %s\n"
-"2. Floppy disk 1: %s\n"
-"3. 1st CDROM: %s\n"
-"4. 2nd CDROM: %s\n"
-"5. 3rd CDROM: %s\n"
-"6. 4th CDROM: %s\n"
-"7. (not implemented)\n"
-"8. Log options for all devices\n"
-"9. Log options for individual devices\n"
-"10. VGA Update Interval: %d\n"
-"11. Mouse: %s\n"
-"12. Keyboard paste delay: %d\n"
-"13. Userbutton shortcut: %s\n"
-"14. Instruction tracing: off (doesn't exist yet)\n"
-"15. Continue simulation\n"
-"16. Quit now\n"
-"\n"
-"Please choose one: [15] ";
-
-#define NOT_IMPLEMENTED(choice) \
- fprintf (stderr, "ERROR: choice %d not implemented\n", choice);
-
-#define BAD_OPTION(menu,choice) \
- do {fprintf (stderr, "ERROR: menu %d has no choice %d\n", menu, choice); \
- assert (0); } while (0)
-
-void build_runtime_options_prompt (char *format, char *buf, int size)
-{
- bx_floppy_options floppyop;
- bx_atadevice_options cdromop;
-/* bx_param_num_c *ips = SIM->get_param_num (BXP_IPS); */
- char buffer[6][128];
- for (int i=0; i<2; i++) {
- SIM->get_floppy_options (i, &floppyop);
- if (floppyop.Odevtype->get () == BX_FLOPPY_NONE)
- strcpy (buffer[i], "(not present)");
- else {
- sprintf (buffer[i], "%s, size=%s, %s", floppyop.Opath->getptr (),
- SIM->get_floppy_type_name (floppyop.Otype->get ()),
- (floppyop.Ostatus->get () == BX_INSERTED)? "inserted" : "ejected");
- if (!floppyop.Opath->getptr ()[0]) strcpy (buffer[i], "none");
- }
- }
-
- // 4 cdroms supported at run time
- int device;
- for (Bit8u cdrom=0; cdrom<4; cdrom++) {
- if (!SIM->get_cdrom_options (cdrom, &cdromop, &device) || !cdromop.Opresent->get ())
- sprintf (buffer[2+cdrom], "(not present)");
- else
- sprintf (buffer[2+cdrom], "(%s on ata%d) %s, %s",
- device&1?"slave":"master", device/2, cdromop.Opath->getptr (),
- (cdromop.Ostatus->get () == BX_INSERTED)? "inserted" : "ejected");
- }
-
- snprintf (buf, size, format, buffer[0], buffer[1], buffer[2],
- buffer[3], buffer[4], buffer[5],
- /* ips->get (), */
- SIM->get_param_num (BXP_VGA_UPDATE_INTERVAL)->get (),
- SIM->get_param_num (BXP_MOUSE_ENABLED)->get () ? "enabled" : "disabled",
- SIM->get_param_num (BXP_KBD_PASTE_DELAY)->get (),
- SIM->get_param_string (BXP_USER_SHORTCUT)->getptr ());
-}
-
-int do_menu (bx_id id) {
- bx_list_c *menu = (bx_list_c *)SIM->get_param (id);
- while (1) {
- menu->get_choice()->set (0);
- int status = menu->text_ask (stdin, stderr);
- if (status < 0) return status;
- bx_param_num_c *choice = menu->get_choice();
- if (choice->get () < 1)
- return choice->get ();
- else {
- int index = choice->get () - 1; // choosing 1 means list[0]
- bx_param_c *chosen = menu->get (index);
- assert (chosen != NULL);
- chosen->text_ask (stdin, stderr);
- }
- }
-}
-
-void askparam (bx_id id)
-{
- bx_param_c *param = SIM->get_param (id);
- param->text_ask (stdin, stderr);
-}
-
-int bx_config_interface (int menu)
-{
- Bit32u choice;
- while (1) {
- switch (menu)
- {
- case BX_CI_INIT:
- bx_config_interface_init ();
- return 0;
- case BX_CI_START_SIMULATION: {
- SIM->begin_simulation (bx_startup_flags.argc, bx_startup_flags.argv);
- // we don't expect it to return, but if it does, quit
- SIM->quit_sim(1);
- break;
- }
- case BX_CI_START_MENU:
- {
- Bit32u default_choice;
- switch (SIM->get_param_enum(BXP_BOCHS_START)->get ()) {
- case BX_LOAD_START:
- default_choice = 2; break;
- case BX_EDIT_START:
- default_choice = 3; break;
- default:
- default_choice = 5; break;
- }
-
- if (ask_uint (startup_menu_prompt, 1, 6, default_choice, &choice, 10) < 0) return -1;
- switch (choice) {
- case 1:
- fprintf (stderr, "I reset all options back to their factory defaults.\n\n");
- SIM->reset_all_param ();
- SIM->get_param_enum(BXP_BOCHS_START)->set(BX_EDIT_START);
- break;
- case 2:
- // Before reading a new configuration, reset every option to its
- // original state.
- SIM->reset_all_param ();
- if (bx_read_rc (NULL) >= 0)
- SIM->get_param_enum(BXP_BOCHS_START)->set(BX_RUN_START);
- break;
- case 3:
- bx_config_interface (BX_CI_START_OPTS);
- SIM->get_param_enum(BXP_BOCHS_START)->set(BX_RUN_START);
- break;
- case 4: bx_write_rc (NULL); break;
- case 5: bx_config_interface (BX_CI_START_SIMULATION); break;
- case 6: SIM->quit_sim (1); return -1;
- default: BAD_OPTION(menu, choice);
- }
- }
- break;
- case BX_CI_START_OPTS:
- {
- char prompt[CI_PATH_LENGTH];
- char oldpath[CI_PATH_LENGTH];
- char olddebuggerpath[CI_PATH_LENGTH];
- char oldprefix[CI_PATH_LENGTH];
- int retval;
-
- retval = SIM->get_log_file (oldpath, CI_PATH_LENGTH);
- assert (retval >= 0);
- double_percent(oldpath,CI_PATH_LENGTH);
- retval = SIM->get_log_prefix (oldprefix, CI_PATH_LENGTH);
- assert (retval >= 0);
- double_percent(oldprefix,CI_PATH_LENGTH);
- retval = SIM->get_debugger_log_file (olddebuggerpath, CI_PATH_LENGTH);
- assert (retval >= 0);
- double_percent(olddebuggerpath,CI_PATH_LENGTH);
-
- sprintf (prompt, startup_options_prompt, oldpath, oldprefix, olddebuggerpath);
- if (ask_uint (prompt, 0, 13, 0, &choice, 10) < 0) return -1;
- switch (choice) {
- case 0: return 0;
- case 1: askparam (BXP_LOG_FILENAME); break;
- case 2: askparam (BXP_LOG_PREFIX); break;
- case 3: askparam (BXP_DEBUGGER_LOG_FILENAME); break;
- case 4: bx_log_options (0); break;
- case 5: bx_log_options (1); break;
- case 6: do_menu (BXP_MENU_MEMORY); break;
- case 7: do_menu (BXP_MENU_INTERFACE); break;
- case 8: do_menu (BXP_MENU_DISK); break;
- case 9: do_menu (BXP_MENU_SERIAL_PARALLEL); break;
- case 10: do_menu (BXP_SB16); break;
- case 11: do_menu (BXP_NE2K); break;
- case 12: do_menu (BXP_MENU_KEYBOARD); break;
- case 13: do_menu (BXP_MENU_MISC); break;
- default: BAD_OPTION(menu, choice);
- }
- }
- break;
- case BX_CI_RUNTIME:
- char prompt[1024];
- bx_floppy_options floppyop;
- bx_atadevice_options cdromop;
- build_runtime_options_prompt (runtime_menu_prompt, prompt, 1024);
- if (ask_uint (prompt, 1, 16, 15, &choice, 10) < 0) return -1;
- switch (choice) {
- case 1:
- SIM->get_floppy_options (0, &floppyop);
- if (floppyop.Odevtype->get () != BX_FLOPPY_NONE) do_menu (BXP_FLOPPYA);
- break;
- case 2:
- SIM->get_floppy_options (1, &floppyop);
- if (floppyop.Odevtype->get () != BX_FLOPPY_NONE) do_menu (BXP_FLOPPYB);
- break;
- case 3:
- case 4:
- case 5:
- case 6:
- int device;
- if (SIM->get_cdrom_options (choice - 3, &cdromop, &device) && cdromop.Opresent->get ()) {
- // disable type selection
- SIM->get_param((bx_id)(BXP_ATA0_MASTER_TYPE + device))->set_enabled(0);
- SIM->get_param((bx_id)(BXP_ATA0_MASTER_MODEL + device))->set_enabled(0);
- SIM->get_param((bx_id)(BXP_ATA0_MASTER_BIOSDETECT + device))->set_enabled(0);
- do_menu ((bx_id)(BXP_ATA0_MASTER + device));
- }
- break;
- case 7: // not implemented yet because I would have to mess with
- // resetting timers and pits and everything on the fly.
- // askparam (BXP_IPS);
- break;
- case 8: bx_log_options (0); break;
- case 9: bx_log_options (1); break;
- case 10: askparam (BXP_VGA_UPDATE_INTERVAL); break;
- case 11: askparam (BXP_MOUSE_ENABLED); break;
- case 12: askparam (BXP_KBD_PASTE_DELAY); break;
- case 13: askparam (BXP_USER_SHORTCUT); break;
- case 14: NOT_IMPLEMENTED (choice); break;
- case 15: fprintf (stderr, "Continuing simulation\n"); return 0;
- case 16:
- fprintf (stderr, "You chose quit on the configuration interface.\n");
- SIM->quit_sim (1);
- return -1;
- default: fprintf (stderr, "Menu choice %d not implemented.\n", choice);
- }
- break;
- default:
- fprintf (stderr, "Unknown config interface menu type.\n");
- assert (menu >=0 && menu < BX_CI_N_MENUS);
- }
- }
-}
-
-static void bx_print_log_action_table ()
-{
- // just try to print all the prefixes first.
- fprintf (stderr, "Current log settings:\n");
- fprintf (stderr, " Debug Info Error Panic Pass\n");
- fprintf (stderr, "ID Device Action Action Action Action Action\n");
- fprintf (stderr, "---- --------- --------- --------- ---------- ---------- ----------\n");
- int i, j, imax=SIM->get_n_log_modules ();
- for (i=0; i<imax; i++) {
- if (strcmp(SIM->get_prefix(i), "[ ]")) {
- fprintf (stderr, "%3d. %s ", i, SIM->get_prefix (i));
- for (j=0; j<SIM->get_max_log_level (); j++) {
- fprintf (stderr, "%10s ", SIM->get_action_name (SIM->get_log_action (i, j)));
- }
- fprintf (stderr, "\n");
- }
- }
-}
-
-static char *log_options_prompt1 = "Enter the ID of the device to edit, or -1 to return: [-1] ";
-static char *log_level_choices[] = { "ignore", "report", "ask", "fatal", "no change" };
-static int log_level_n_choices_normal = 4;
-
-void bx_log_options (int individual)
-{
- if (individual) {
- int done = 0;
- while (!done) {
- bx_print_log_action_table ();
- Bit32s id, level, action;
- Bit32s maxid = SIM->get_n_log_modules ();
- if (ask_int (log_options_prompt1, -1, maxid-1, -1, &id) < 0)
- return;
- if (id < 0) return;
- fprintf (stderr, "Editing log options for the device %s\n", SIM->get_prefix (id));
- for (level=0; level<SIM->get_max_log_level (); level++) {
- char prompt[1024];
- int default_action = SIM->get_log_action (id, level);
- sprintf (prompt, "Enter action for %s event: [%s] ", SIM->get_log_level_name (level), SIM->get_action_name(default_action));
- // don't show the no change choice (choices=3)
- if (ask_menu (prompt, log_level_n_choices_normal, log_level_choices, default_action, &action)<0)
- return;
- SIM->set_log_action (id, level, action);
- }
- }
- } else {
- // provide an easy way to set log options for all devices at once
- bx_print_log_action_table ();
- for (int level=0; level<SIM->get_max_log_level (); level++) {
- char prompt[1024];
- int action, default_action = 3; // default to no change
- sprintf (prompt, "Enter action for %s event on all devices: [no change] ", SIM->get_log_level_name (level));
- // do show the no change choice (choices=4)
- if (ask_menu (prompt, log_level_n_choices_normal+1, log_level_choices, default_action, &action)<0)
- return;
- if (action < 3) {
- SIM->set_default_log_action (level, action);
- SIM->set_log_action (-1, level, action);
- }
- }
- }
-}
-
-int bx_read_rc (char *rc)
-{
- if (rc && SIM->read_rc (rc) >= 0) return 0;
- char oldrc[CI_PATH_LENGTH];
- if (SIM->get_default_rc (oldrc, CI_PATH_LENGTH) < 0)
- strcpy (oldrc, "none");
- char newrc[CI_PATH_LENGTH];
- while (1) {
- if (ask_string ("\nWhat is the configuration file name?\nTo cancel, type 'none'. [%s] ", oldrc, newrc) < 0) return -1;
- if (!strcmp (newrc, "none")) return -1;
- if (SIM->read_rc (newrc) >= 0) return 0;
- fprintf (stderr, "The file '%s' could not be found.\n", newrc);
- }
-}
-
-int bx_write_rc (char *rc)
-{
- char oldrc[CI_PATH_LENGTH], newrc[CI_PATH_LENGTH];
- if (rc == NULL) {
- if (SIM->get_default_rc (oldrc, CI_PATH_LENGTH) < 0)
- strcpy (oldrc, "none");
- } else {
- strncpy (oldrc, rc, CI_PATH_LENGTH);
- }
- while (1) {
- if (ask_string ("Save configuration to what file? To cancel, type 'none'.\n[%s] ", oldrc, newrc) < 0) return -1;
- if (!strcmp (newrc, "none")) return 0;
- // try with overwrite off first
- int status = SIM->write_rc (newrc, 0);
- if (status >= 0) {
- fprintf (stderr, "Wrote configuration to '%s'.\n", newrc);
- return 0;
- } else if (status == -2) {
- // return code -2 indicates the file already exists, and overwrite
- // confirmation is required.
- Bit32u overwrite = 0;
- char prompt[256];
- sprintf (prompt, "Configuration file '%s' already exists. Overwrite it? [no] ", newrc);
- if (ask_yn (prompt, 0, &overwrite) < 0) return -1;
- if (!overwrite) continue; // if "no", start loop over, asking for a different file
- // they confirmed, so try again with overwrite bit set
- if (SIM->write_rc (newrc, 1) >= 0) {
- fprintf (stderr, "Overwriting existing configuration '%s'.\n", newrc);
- return 0;
- } else {
- fprintf (stderr, "Write failed to '%s'.\n", newrc);
- }
- }
- }
-}
-
-char *log_action_ask_choices[] = { "cont", "alwayscont", "die", "abort", "debug" };
-int log_action_n_choices = 4 + (BX_DEBUGGER?1:0);
-
-BxEvent *
-config_interface_notify_callback (void *unused, BxEvent *event)
-{
-#ifdef WIN32
- int opts;
- bx_param_c *param;
- bx_param_string_c *sparam;
-#endif
- event->retcode = -1;
- switch (event->type)
- {
- case BX_SYNC_EVT_TICK:
- event->retcode = 0;
- return event;
- case BX_SYNC_EVT_ASK_PARAM:
-#ifdef WIN32
- param = event->u.param.param;
- if (param->get_type() == BXT_PARAM_STRING) {
- sparam = (bx_param_string_c *)param;
- opts = sparam->get_options()->get();
- if (opts & sparam->IS_FILENAME) {
- if (param->get_id() == BXP_NULL) {
- event->retcode = AskFilename(GetBochsWindow(), (bx_param_filename_c *)sparam);
- } else {
- event->retcode = FloppyDialog((bx_param_filename_c *)sparam);
- }
- return event;
- } else {
- event->retcode = AskString(sparam);
- return event;
- }
- }
-#endif
- event->u.param.param->text_ask (stdin, stderr);
- return event;
- case BX_SYNC_EVT_LOG_ASK:
- {
-#ifdef WIN32
- LogAskDialog(event);
-#else
- int level = event->u.logmsg.level;
- fprintf (stderr, "\a========================================================================\n");
- fprintf (stderr, "Event type: %s\n", SIM->get_log_level_name (level));
- fprintf (stderr, "Device: %s\n", event->u.logmsg.prefix);
- fprintf (stderr, "Message: %s\n\n", event->u.logmsg.msg);
- fprintf (stderr, "A %s has occurred. Do you want to:\n", SIM->get_log_level_name (level));
- fprintf (stderr, " cont - continue execution\n");
- fprintf (stderr, " alwayscont - continue execution, and don't ask again.\n");
- fprintf (stderr, " This affects only %s events from device %s\n", SIM->get_log_level_name (level), event->u.logmsg.prefix);
- fprintf (stderr, " die - stop execution now\n");
- fprintf (stderr, " abort - dump core %s\n",
- BX_HAVE_ABORT ? "" : "(Disabled)");
-#if BX_DEBUGGER
- fprintf (stderr, " debug - continue and return to bochs debugger\n");
-#endif
- int choice;
-ask:
- if (ask_menu ("Choose one of the actions above: [%s] ",
- log_action_n_choices, log_action_ask_choices, 2, &choice) < 0)
- event->retcode = -1;
- // return 0 for continue, 1 for alwayscontinue, 2 for die, 3 for debug.
- if (!BX_HAVE_ABORT && choice==BX_LOG_ASK_CHOICE_DUMP_CORE) goto ask;
- fflush(stdout);
- fflush(stderr);
- event->retcode = choice;
-#endif
- }
- return event;
- case BX_ASYNC_EVT_REFRESH:
- case BX_ASYNC_EVT_DBG_MSG:
- // The text mode interface does not use these events, so just ignore
- // them.
- return event;
- default:
- fprintf (stderr, "Control panel: notify callback called with event type %04x\n", event->type);
- return event;
- }
- assert (0); // switch statement should return
-}
-
-void bx_config_interface_init () {
- //fprintf (stderr, "bx_config_interface_init()\n");
- SIM->set_notify_callback (config_interface_notify_callback, NULL);
-}
-
-/////////////////////////////////////////////////////////////////////
-// implement the text_* methods for bx_param types.
-
-void
-bx_param_num_c::text_print (FILE *fp)
-{
- //fprintf (fp, "number parameter, id=%u, name=%s\n", get_id (), get_name ());
- //fprintf (fp, "value=%u\n", get ());
- if (get_format ()) {
- fprintf (fp, get_format (), get ());
- } else {
- char *format = "%s: %d";
- assert (base==10 || base==16);
- if (base==16) format = "%s: 0x%x";
- fprintf (fp, format, get_name (), get ());
- }
-}
-
-void
-bx_param_bool_c::text_print (FILE *fp)
-{
- if (get_format ()) {
- fprintf (fp, get_format (), get () ? "yes" : "no");
- } else {
- char *format = "%s: %s";
- fprintf (fp, format, get_name (), get () ? "yes" : "no");
- }
-}
-
-void
-bx_param_enum_c::text_print (FILE *fp)
-{
- int n = get ();
- assert (n >= min && n <= max);
- char *choice = choices[n - min];
- if (get_format ()) {
- fprintf (fp, get_format (), choice);
- } else {
- char *format = "%s: %s";
- fprintf (fp, format, get_name (), choice);
- }
-}
-
-void
-bx_param_string_c::text_print (FILE *fp)
-{
- char *value = getptr ();
- int opts = options->get ();
- if (opts & RAW_BYTES) {
- char buffer[1024];
- buffer[0] = 0;
- char sep_string[2];
- sep_string[0] = separator;
- sep_string[1] = 0;
- for (int i=0; i<maxsize; i++) {
- char eachbyte[16];
- sprintf (eachbyte, "%s%02x", (i>0)?sep_string : "", (unsigned int)0xff&val[i]);
- strncat (buffer, eachbyte, sizeof(buffer));
- }
- if (strlen (buffer) > sizeof(buffer)-4) {
- assert (0); // raw byte print buffer is probably overflowing. increase the max or make it dynamic
- }
- value = buffer;
- }
- if (get_format ()) {
- fprintf (fp, get_format (), value);
- } else {
- fprintf (fp, "%s: %s", get_name (), value);
- }
-}
-
-void
-bx_list_c::text_print (FILE *fp)
-{
- //fprintf (fp, "This is a list.\n");
- //fprintf (fp, "title=%s\n", title->getptr ());
- fprintf (fp, "%s: ", get_name ());
- /*
- fprintf (fp, "options=%s%s%s\n",
- (options->get () == 0) ? "none" : "",
- (options->get () & SHOW_PARENT) ? "SHOW_PARENT " : "",
- (options->get () & SERIES_ASK) ? "SERIES_ASK " : "");
- */
- for (int i=0; i<size; i++) {
- //fprintf (fp, "param[%d] = %p\n", i, list[i]);
- assert (list[i] != NULL);
- if (list[i]->get_enabled ()) {
- if ((i>0) && (options->get () & SERIES_ASK))
- fprintf (fp, ", ");
- list[i]->text_print (fp);
- if (!(options->get () & SERIES_ASK))
- fprintf (fp, "\n");
- }
- }
-}
-
-int
-bx_param_num_c::text_ask (FILE *fpin, FILE *fpout)
-{
- fprintf (fpout, "\n");
- int status;
- char *prompt = get_ask_format ();
- if (prompt == NULL) {
- // default prompt, if they didn't set an ask format string
- text_print (fpout);
- fprintf (fpout, "\n");
- prompt = "Enter new value: [%d] ";
- if (base==16)
- prompt = "Enter new value in hex: [%x] ";
- }
- Bit32u n = get ();
- status = ask_uint (prompt, min, max, n, &n, base);
- if (status < 0) return status;
- set (n);
- return 0;
-}
-
-int
-bx_param_bool_c::text_ask (FILE *fpin, FILE *fpout)
-{
- fprintf (fpout, "\n");
- int status;
- char *prompt = get_ask_format ();
- char buffer[512];
- if (prompt == NULL) {
- // default prompt, if they didn't set an ask format string
- sprintf (buffer, "%s? [%%s] ", get_name ());
- prompt = buffer;
- }
- Bit32u n = get ();
- status = ask_yn (prompt, n, &n);
- if (status < 0) return status;
- set (n);
- return 0;
-}
-
-int
-bx_param_enum_c::text_ask (FILE *fpin, FILE *fpout)
-{
- fprintf (fpout, "\n");
- char *prompt = get_ask_format ();
- if (prompt == NULL) {
- // default prompt, if they didn't set an ask format string
- fprintf (fpout, "%s = ", get_name ());
- text_print (fpout);
- fprintf (fpout, "\n");
- prompt = "Enter new value: [%s] ";
- }
- Bit32s n = (Bit32s)(get () - min);
- int status = ask_menu (prompt, (max-min+1), choices, n, &n);
- if (status < 0) return status;
- n += (Bit32s)min;
- set (n);
- return 0;
-}
-
-int parse_raw_bytes (char *dest, char *src, int destsize, char separator)
-{
- //printf ("parsing src='%s'\n", src);
- int i;
- unsigned int n;
- for (i=0; i<destsize; i++)
- dest[i] = 0;
- for (i=0; i<destsize; i++) {
- while (*src == separator)
- src++;
- if (*src == 0) break;
- // try to read a byte of hex
- if (sscanf (src, "%02x", &n) == 1) {
- //printf ("found a byte %02x\n", n);
- dest[i] = n;
- src+=2;
- } else {
- return -1;
- }
- }
- return 0;
-}
-
-int
-bx_param_string_c::text_ask (FILE *fpin, FILE *fpout)
-{
- fprintf (fpout, "\n");
- int status;
- char *prompt = get_ask_format ();
- if (prompt == NULL) {
- // default prompt, if they didn't set an ask format string
- text_print (fpout);
- fprintf (fpout, "\n");
- prompt = "Enter a new value, or press return for no change.\n";
- }
- while (1) {
- char buffer[1024];
- status = ask_string (prompt, getptr(), buffer);
- if (status < 0) return status;
- int opts = options->get ();
- char buffer2[1024];
- strcpy (buffer2, buffer);
- if (status == 1 && opts & RAW_BYTES) {
- // copy raw hex into buffer
- status = parse_raw_bytes (buffer, buffer2, maxsize, separator);
- if (status < 0) {
- fprintf (fpout, "Illegal raw byte format. I expected something like 3A%c03%c12%c...\n", separator, separator, separator);
- continue;
- }
- }
- if (!equals (buffer))
- set (buffer);
- return 0;
- }
-}
-
-int
-bx_list_c::text_ask (FILE *fpin, FILE *fpout)
-{
- char *my_title = title->getptr ();
- fprintf (fpout, "\n");
- int i, imax = strlen (my_title);
- for (i=0; i<imax; i++) fprintf (fpout, "-");
- fprintf (fpout, "\n%s\n", my_title);
- for (i=0; i<imax; i++) fprintf (fpout, "-");
- fprintf (fpout, "\n"); //fprintf (fp, "options=%s\n", options->get ());
- if (options->get () & SERIES_ASK) {
- for (int i=0; i<size; i++) {
- if (list[i]->get_enabled ())
- list[i]->text_ask (fpin, fpout);
- }
- } else {
- if (options->get () & SHOW_PARENT)
- fprintf (fpout, "0. Return to previous menu\n");
- for (int i=0; i<size; i++) {
- assert (list[i] != NULL);
- fprintf (fpout, "%d. ", i+1);
- if (list[i]->get_enabled ()) {
- list[i]->text_print (fpout);
- fprintf (fpout, "\n");
- } else
- fprintf (fpout, "(disabled)\n");
- }
- fprintf (fpout, "\n");
- Bit32u n = choice->get ();
- int min = (options->get () & SHOW_PARENT) ? 0 : 1;
- int max = size;
- int status = ask_uint ("Please choose one: [%d] ", min, max, n, &n, 10);
- if (status < 0) return status;
- choice->set (n);
- }
- return 0;
-}
-
-static int ci_callback (void *userdata, ci_command_t command)
-{
- switch (command)
- {
- case CI_START:
- //fprintf (stderr, "textconfig.cc: start\n");
- bx_config_interface_init ();
- if (SIM->get_param_enum(BXP_BOCHS_START)->get () == BX_QUICK_START)
- bx_config_interface (BX_CI_START_SIMULATION);
- else {
- if (!SIM->test_for_text_console ())
- return CI_ERR_NO_TEXT_CONSOLE;
- bx_config_interface (BX_CI_START_MENU);
- }
- break;
- case CI_RUNTIME_CONFIG:
- bx_config_interface (BX_CI_RUNTIME);
- break;
- case CI_SHUTDOWN:
- //fprintf (stderr, "textconfig.cc: shutdown\n");
- break;
- }
- return 0;
-}
-
-// if I can make things compile without this module linked in, then
-// this file can become a plugin too.
-int init_text_config_interface ()
-{
- //fprintf (stderr, "plugin_init for textconfig.cc\n");
- SIM->register_configuration_interface ("textconfig", ci_callback, NULL);
- return 0; // success
-}
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: textconfig.h,v 1.1 2002/10/29 20:16:04 bdenney Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-enum {
- BX_CI_INIT,
- BX_CI_START_MENU,
- BX_CI_START_OPTS,
- BX_CI_START_OPTS_MEM,
- BX_CI_START_OPTS_INTERFACE,
- BX_CI_START_OPTS_DISK,
- BX_CI_START_OPTS_SOUND,
- BX_CI_START_OPTS_MISC,
- BX_CI_START_SIMULATION,
- BX_CI_RUNTIME,
- BX_CI_N_MENUS
-};
-
-int init_text_config_interface ();
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: x.cc,v 1.76 2003/08/11 19:27:57 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-#define XK_PUBLISHING
-#define XK_TECHNICAL
-
-// Define BX_PLUGGABLE in files that can be compiled into plugins. For
-// platforms that require a special tag on exported symbols, BX_PLUGGABLE
-// is used to know when we are exporting symbols and when we are importing.
-#define BX_PLUGGABLE
-
-#include "bochs.h"
-#if BX_WITH_X11
-
-extern "C" {
-#include <X11/Xlib.h>
-#include <X11/Xutil.h>
-#include <X11/Xos.h>
-#include <X11/Xatom.h>
-#include <X11/keysym.h>
-#if BX_HAVE_XPM_H
-#include <X11/xpm.h>
-#endif
-}
-
-#if BX_HAVE_XPM_H
-#include "icon_bochs.xpm"
-#else
-#include "icon_bochs.h"
-#endif
-
-#include "font/vga.bitmap.h"
-
-class bx_x_gui_c : public bx_gui_c {
-public:
- bx_x_gui_c (void);
- DECLARE_GUI_VIRTUAL_METHODS()
-#if BX_USE_IDLE_HACK
- virtual void sim_is_idle(void);
-#endif
-};
-
-// declare one instance of the gui object and call macro to insert the
-// plugin code
-static bx_x_gui_c *theGui = NULL;
-IMPLEMENT_GUI_PLUGIN_CODE(x)
-
-#define LOG_THIS theGui->
-
-#define MAX_MAPPED_STRING_LENGTH 10
-
-/* These are used as arguments to nearly every Xlib routine, so it saves
- * routine arguments to declare them global. If there were
- * additional source files, they would be declared extern there. */
-Display *bx_x_display;
-int bx_x_screen_num;
-static Colormap default_cmap;
-static unsigned long white_pixel=0, black_pixel=0;
-
-static char *progname; /* name this program was invoked by */
-
-static unsigned int text_rows=25, text_cols=80;
-static Bit8u h_panning = 0, v_panning = 0;
-
-static Window win;
-static GC gc, gc_inv, gc_headerbar, gc_headerbar_inv;
-static unsigned font_width, font_height;
-static unsigned dimension_x=0, dimension_y=0;
-static unsigned vga_bpp=8;
-
-static XImage *ximage = NULL;
-static unsigned imDepth, imWide, imBPP;
-
-// current cursor coordinates
-static int prev_x=-1, prev_y=-1;
-static int current_x=-1, current_y=-1;
-static unsigned mouse_button_state = 0;
-
-static unsigned prev_cursor_x=0;
-static unsigned prev_cursor_y=0;
-
-static int warp_home_x = 200;
-static int warp_home_y = 200;
-static int mouse_enable_x = 0;
-static int mouse_enable_y = 0;
-static int warp_dx = 0;
-static int warp_dy = 0;
-
-static void warp_cursor(int dx, int dy);
-static void disable_cursor();
-static void enable_cursor();
-
-static Bit32u convertStringToXKeysym (const char *string);
-
-static bx_bool x_init_done = false;
-
-static Pixmap vgafont[256];
-
-struct {
- Pixmap bmap;
- unsigned xdim;
- unsigned ydim;
- } bx_bitmaps[BX_MAX_PIXMAPS];
-unsigned bx_bitmap_entries = 0;
-
-static struct {
- Pixmap bitmap;
- unsigned xdim;
- unsigned ydim;
- unsigned xorigin;
- unsigned yorigin;
- unsigned alignment;
- void (*f)(void);
- } bx_headerbar_entry[BX_MAX_HEADERBAR_ENTRIES];
-static unsigned bx_headerbar_y = 0;
-static unsigned bx_headerbar_entries = 0;
-static unsigned bx_bitmap_left_xorigin = 0; // pixels from left
-static unsigned bx_bitmap_right_xorigin = 0; // pixels from right
-
-static void headerbar_click(int x, int y);
-static void send_keyboard_mouse_status(void);
-
-
-
-
-Bit32u ascii_to_key_event[0x5f] = {
- // !"#$%&'
- BX_KEY_SPACE,
- BX_KEY_1,
- BX_KEY_SINGLE_QUOTE,
- BX_KEY_3,
- BX_KEY_4,
- BX_KEY_5,
- BX_KEY_7,
- BX_KEY_SINGLE_QUOTE,
-
- // ()*+,-./
- BX_KEY_9,
- BX_KEY_0,
- BX_KEY_8,
- BX_KEY_EQUALS,
- BX_KEY_COMMA,
- BX_KEY_MINUS,
- BX_KEY_PERIOD,
- BX_KEY_SLASH,
-
- // 01234567
- BX_KEY_0,
- BX_KEY_1,
- BX_KEY_2,
- BX_KEY_3,
- BX_KEY_4,
- BX_KEY_5,
- BX_KEY_6,
- BX_KEY_7,
-
- // 89:;<=>?
- BX_KEY_8,
- BX_KEY_9,
- BX_KEY_SEMICOLON,
- BX_KEY_SEMICOLON,
- BX_KEY_COMMA,
- BX_KEY_EQUALS,
- BX_KEY_PERIOD,
- BX_KEY_SLASH,
-
- // @ABCDEFG
- BX_KEY_2,
- BX_KEY_A,
- BX_KEY_B,
- BX_KEY_C,
- BX_KEY_D,
- BX_KEY_E,
- BX_KEY_F,
- BX_KEY_G,
-
-
- // HIJKLMNO
- BX_KEY_H,
- BX_KEY_I,
- BX_KEY_J,
- BX_KEY_K,
- BX_KEY_L,
- BX_KEY_M,
- BX_KEY_N,
- BX_KEY_O,
-
-
- // PQRSTUVW
- BX_KEY_P,
- BX_KEY_Q,
- BX_KEY_R,
- BX_KEY_S,
- BX_KEY_T,
- BX_KEY_U,
- BX_KEY_V,
- BX_KEY_W,
-
- // XYZ[\]^_
- BX_KEY_X,
- BX_KEY_Y,
- BX_KEY_Z,
- BX_KEY_LEFT_BRACKET,
- BX_KEY_BACKSLASH,
- BX_KEY_RIGHT_BRACKET,
- BX_KEY_6,
- BX_KEY_MINUS,
-
- // `abcdefg
- BX_KEY_GRAVE,
- BX_KEY_A,
- BX_KEY_B,
- BX_KEY_C,
- BX_KEY_D,
- BX_KEY_E,
- BX_KEY_F,
- BX_KEY_G,
-
- // hijklmno
- BX_KEY_H,
- BX_KEY_I,
- BX_KEY_J,
- BX_KEY_K,
- BX_KEY_L,
- BX_KEY_M,
- BX_KEY_N,
- BX_KEY_O,
-
- // pqrstuvw
- BX_KEY_P,
- BX_KEY_Q,
- BX_KEY_R,
- BX_KEY_S,
- BX_KEY_T,
- BX_KEY_U,
- BX_KEY_V,
- BX_KEY_W,
-
- // xyz{|}~
- BX_KEY_X,
- BX_KEY_Y,
- BX_KEY_Z,
- BX_KEY_LEFT_BRACKET,
- BX_KEY_BACKSLASH,
- BX_KEY_RIGHT_BRACKET,
- BX_KEY_GRAVE
- };
-
-extern Bit8u graphics_snapshot[32 * 1024];
-
-
-static void create_internal_vga_font(void);
-static void xkeypress(KeySym keysym, int press_release);
-// extern "C" void select_visual(void);
-
-#define ROUNDUP(nbytes, pad) ((((nbytes) + ((pad)-1)) / (pad)) * ((pad)>>3))
-
-
-#define MAX_VGA_COLORS 256
-
-unsigned long col_vals[MAX_VGA_COLORS]; // 256 VGA colors
-unsigned curr_foreground, curr_background;
-
-static unsigned x_tilesize, y_tilesize;
-
-
-// Try to allocate NCOLORS at once in the colormap provided. If it can
-// be done, return true. If not, return false. (In either case, free
-// up the color cells so that we don't add to the problem!) This is used
-// to determine whether Bochs should use a private colormap even when the
-// user did not specify it.
-static bx_bool
-test_alloc_colors (Colormap cmap, Bit32u n_tries) {
- XColor color;
- unsigned long pixel[MAX_VGA_COLORS];
- bx_bool pixel_valid[MAX_VGA_COLORS];
- Bit32u n_allocated = 0;
- Bit32u i;
- color.flags = DoRed | DoGreen | DoBlue;
- for (i=0; i<n_tries; i++) {
- // choose wierd color values that are unlikely to already be in the
- // colormap.
- color.red = ((i+41)%MAX_VGA_COLORS) << 8;
- color.green = ((i+42)%MAX_VGA_COLORS) << 8;
- color.blue = ((i+43)%MAX_VGA_COLORS) << 8;
- pixel_valid[i] = false;
- if (XAllocColor (bx_x_display, cmap, &color)) {
- pixel[i] = color.pixel;
- pixel_valid[i] = true;
- n_allocated++;
- }
- }
- BX_INFO (("test_alloc_colors: %d colors available out of %d colors tried", n_allocated, n_tries));
- // now free them all
- for (i=0; i<n_tries; i++) {
- if (pixel_valid[i]) XFreeColors (bx_x_display, cmap, &pixel[i], 1, 0);
- }
- return (n_allocated == n_tries);
-}
-
-bx_x_gui_c::bx_x_gui_c () {
-}
-
- void
-bx_x_gui_c::specific_init(int argc, char **argv, unsigned tilewidth, unsigned tileheight,
- unsigned headerbar_y)
-{
- unsigned i;
- int x, y; /* window position */
- unsigned int border_width = 4; /* four pixels */
-#if BX_CPU_LEVEL < 2
- char *window_name = "Bochs 8086 emulator, http://bochs.sourceforge.net/";
-#elif BX_CPU_LEVEL == 2
- char *window_name = "Bochs 80286 emulator, http://bochs.sourceforge.net/";
-#elif BX_CPU_LEVEL == 3
- char *window_name = "Bochs 80386 emulator, http://bochs.sourceforge.net/";
-#elif BX_CPU_LEVEL == 4
- char *window_name = "Bochs 80486 emulator, http://bochs.sourceforge.net/";
-#else
- char *window_name = "VTXen";
-#endif
- char *icon_name = "Bochs";
- Pixmap icon_pixmap;
-#if BX_HAVE_XPM_H
- Pixmap icon_mask;
-#endif
- XSizeHints size_hints;
- char *display_name = NULL;
- /* create GC for text and drawing */
- unsigned long valuemask = 0; /* ignore XGCvalues and use defaults */
- XGCValues values;
- Visual *default_visual;
- int default_depth;
- XEvent report;
- XSetWindowAttributes win_attr;
- unsigned long plane_masks_return[1];
- XColor color;
-
- put("XGUI");
-
- x_tilesize = tilewidth;
- y_tilesize = tileheight;
- bx_headerbar_y = headerbar_y;
-
- progname = argv[0];
-
- /* connect to X server */
- if ( (bx_x_display=XOpenDisplay(display_name)) == NULL )
- {
- BX_PANIC(("%s: cannot connect to X server %s",
- progname, XDisplayName(display_name)));
- }
-
- /* get screen size from display structure macro */
- bx_x_screen_num = DefaultScreen(bx_x_display);
-
- /* Note that in a real application, x and y would default to 0
- * but would be settable from the command line or resource database.
- */
- x = y = 0;
-
-
- // Temporary values so we can create the window
- font_width = 8;
- font_height = 16;
-
- dimension_x = text_cols * font_width;
- dimension_y = text_rows * font_height + headerbar_y;
-
- /* create opaque window */
- win = XCreateSimpleWindow(bx_x_display, RootWindow(bx_x_display,bx_x_screen_num),
- x, y,
- dimension_x,
- dimension_y,
- border_width,
- BlackPixel(bx_x_display, bx_x_screen_num),
- BlackPixel(bx_x_display, bx_x_screen_num));
-
- // (attempt to) enable backing store
- win_attr.save_under=1;
- win_attr.backing_store=Always;
- XChangeWindowAttributes(bx_x_display,win,CWSaveUnder|CWBackingStore,&win_attr);
-
- default_depth = DefaultDepth(bx_x_display, bx_x_screen_num);
- default_visual = DefaultVisual(bx_x_display, bx_x_screen_num);
-
- if (!bx_options.Oprivate_colormap->get ()) {
- default_cmap = DefaultColormap(bx_x_display, bx_x_screen_num);
- // try to use default colormap. If not enough colors are available,
- // then switch to private colormap despite the user setting. There
- // are too many cases when no colors are available and Bochs simply
- // draws everything in black on black.
- if (!test_alloc_colors (default_cmap, 16)) {
- BX_ERROR (("I can't even allocate 16 colors! Switching to a private colormap"));
- bx_options.Oprivate_colormap->set (1);
- }
- col_vals[0] = BlackPixel(bx_x_display, bx_x_screen_num);
- col_vals[15] = WhitePixel(bx_x_display, bx_x_screen_num);
- for (i = 1; i < MAX_VGA_COLORS; i++) {
- if (i==15) continue;
- col_vals[i] = col_vals[0];
- }
- }
-
- if (bx_options.Oprivate_colormap->get ()) {
- default_cmap = XCreateColormap(bx_x_display, DefaultRootWindow(bx_x_display),
- default_visual, AllocNone);
- if (XAllocColorCells(bx_x_display, default_cmap, False,
- plane_masks_return, 0, col_vals, MAX_VGA_COLORS) == 0) {
- BX_PANIC(("XAllocColorCells returns error. Maybe your screen does not support a private colormap?"));
- }
-
- win_attr.colormap = default_cmap;
- XChangeWindowAttributes(bx_x_display, win, CWColormap, &win_attr);
-
- color.flags = DoRed | DoGreen | DoBlue;
-
- for (i=0; i < MAX_VGA_COLORS; i++) {
- color.pixel = i;
- if (i==15) {
- color.red = 0xffff;
- color.green = 0xffff;
- color.blue = 0xffff;
- }
- else {
- color.red = 0;
- color.green = 0;
- color.blue = 0;
- }
- XStoreColor(bx_x_display, default_cmap, &color);
- }
- }
-
- // convenience variables which hold the black & white color indeces
- black_pixel = col_vals[0];
- white_pixel = col_vals[15];
-
- BX_INFO(("font %u wide x %u high, display depth = %d",
- (unsigned) font_width, (unsigned) font_height, default_depth));
-
- //select_visual();
-
-
- /* Get available icon sizes from Window manager */
-
-#if BX_HAVE_XPM_H
- /* Create pixmap from XPM for icon */
- XCreatePixmapFromData(bx_x_display, win, icon_bochs_xpm, &icon_pixmap, &icon_mask, NULL);
-#else
- /* Create pixmap of depth 1 (bitmap) for icon */
- icon_pixmap = XCreateBitmapFromData(bx_x_display, win,
- (char *) bochs_icon_bits, bochs_icon_width, bochs_icon_height);
-#endif
-
- /* Set size hints for window manager. The window manager may
- * override these settings. Note that in a real
- * application if size or position were set by the user
- * the flags would be UPosition and USize, and these would
- * override the window manager's preferences for this window. */
- /* x, y, width, and height hints are now taken from
- * the actual settings of the window when mapped. Note
- * that PPosition and PSize must be specified anyway. */
-
- size_hints.flags = PPosition | PSize | PMinSize | PMaxSize;
- size_hints.max_width = size_hints.min_width = dimension_x;
- size_hints.max_height = size_hints.min_height = dimension_y;
-
- {
- XWMHints wm_hints;
- XClassHint class_hints;
-
- /* format of the window name and icon name
- * arguments has changed in R4 */
- XTextProperty windowName, iconName;
-
- /* These calls store window_name and icon_name into
- * XTextProperty structures and set their other
- * fields properly. */
- if (XStringListToTextProperty(&window_name, 1, &windowName) == 0) {
- BX_PANIC(("%s: structure allocation for windowName failed.",
- progname));
- }
-
- if (XStringListToTextProperty(&icon_name, 1, &iconName) == 0) {
- BX_PANIC(("%s: structure allocation for iconName failed.",
- progname));
- }
-
- wm_hints.initial_state = NormalState;
- wm_hints.input = True;
- wm_hints.icon_pixmap = icon_pixmap;
-#if BX_HAVE_XPM_H
- wm_hints.icon_mask = icon_mask;
- wm_hints.flags = StateHint | IconPixmapHint | IconMaskHint | InputHint;
-#else
- wm_hints.flags = StateHint | IconPixmapHint | InputHint;
-#endif
- class_hints.res_name = progname;
- class_hints.res_class = "Bochs";
-
- XSetWMProperties(bx_x_display, win, &windowName, &iconName,
- argv, argc, &size_hints, &wm_hints,
- &class_hints);
- }
-
- /* Select event types wanted */
- XSelectInput(bx_x_display, win, ExposureMask | KeyPressMask | KeyReleaseMask |
- ButtonPressMask | ButtonReleaseMask | StructureNotifyMask | PointerMotionMask |
- EnterWindowMask | LeaveWindowMask );
-
-
- /* Create default Graphics Context */
- gc = XCreateGC(bx_x_display, win, valuemask, &values);
- gc_inv = XCreateGC(bx_x_display, win, valuemask, &values);
- gc_headerbar = XCreateGC(bx_x_display, win, valuemask, &values);
- gc_headerbar_inv = XCreateGC(bx_x_display, win, valuemask, &values);
-
- XSetState(bx_x_display, gc, white_pixel, black_pixel, GXcopy,AllPlanes);
-
- XSetState(bx_x_display, gc_inv, black_pixel, white_pixel, GXinvert,AllPlanes);
-
- XSetState(bx_x_display, gc_headerbar, black_pixel, white_pixel, GXcopy,AllPlanes);
-
- XSetState(bx_x_display, gc_headerbar_inv, white_pixel, black_pixel, GXcopy,AllPlanes);
-
-
- /* Display window */
- XMapWindow(bx_x_display, win);
- XSync(bx_x_display, /* no discard */ 0);
-
- BX_DEBUG(("waiting for MapNotify"));
- while (1) {
- XNextEvent(bx_x_display, &report);
- if (report.type == MapNotify) break;
- }
- BX_DEBUG(("MapNotify found."));
-
- // Create the VGA font
- create_internal_vga_font();
-
-
-{
- char *imagedata;
-
- ximage = XCreateImage(bx_x_display, default_visual,
- default_depth, // depth of image (bitplanes)
- ZPixmap,
- 0, // offset
- NULL, // malloc() space after
- x_tilesize, y_tilesize, // x & y size of image
- 32, // # bits of padding
- 0 ); // bytes_per_line, let X11 calculate
- if (!ximage)
- BX_PANIC(("vga: couldn't XCreateImage()"));
-
- imDepth = default_depth;
- imWide = ximage->bytes_per_line;
- imBPP = ximage->bits_per_pixel;
-
- imagedata = (char *) malloc( (size_t) (ximage->bytes_per_line * y_tilesize) );
- if (!imagedata) BX_PANIC(("imagedata: malloc returned error"));
-
- ximage->data = imagedata;
-
- if (imBPP < imDepth) {
- BX_PANIC(("vga_x: bits_per_pixel < depth ?"));
- }
-
- x_init_done = true;
-
-}
-
- curr_background = 0;
- XSetBackground(bx_x_display, gc, col_vals[curr_background]);
- curr_foreground = 1;
- XSetForeground(bx_x_display, gc, col_vals[curr_foreground]);
- //XGrabPointer( bx_x_display, win, True, 0, GrabModeAsync, GrabModeAsync,
- // win, None, CurrentTime );
-
-
- XFlush(bx_x_display);
-
- // loads keymap for x11
- if(bx_options.keyboard.OuseMapping->get()) {
- bx_keymap.loadKeymap(convertStringToXKeysym);
- }
-}
-
-
-// This is called whenever the mouse_enabled parameter changes. It
-// can change because of a gui event such as clicking on the mouse-enable
-// bitmap or pressing the middle button, or from the configuration interface.
-// In all those cases, setting the parameter value will get you here.
- void
-bx_x_gui_c::mouse_enabled_changed_specific (bx_bool val)
-{
- BX_DEBUG (("mouse_enabled=%d, x11 specific code", val?1:0));
- if (val) {
- BX_INFO(("[x] Mouse on"));
- mouse_enable_x = current_x;
- mouse_enable_y = current_y;
- disable_cursor();
- // Move the cursor to a 'safe' place
- warp_cursor(warp_home_x-current_x, warp_home_y-current_y);
- } else {
- BX_INFO(("[x] Mouse off"));
- enable_cursor();
- warp_cursor(mouse_enable_x-current_x, mouse_enable_y-current_y);
- }
-}
-
- void
-create_internal_vga_font(void)
-{
- // Default values
- font_width=8;
- font_height=16;
-
- for(int i=0; i<256; i++) {
- vgafont[i]=XCreateBitmapFromData(bx_x_display, win, (const char*)bx_vgafont[i].data,
- font_width, font_height);
- if(vgafont[i] == None)
- BX_PANIC(("Can't create vga font [%d]", i));
- }
-}
-
- void
-bx_x_gui_c::handle_events(void)
-{
- XEvent report;
- XKeyEvent *key_event;
- KeySym keysym;
- XComposeStatus compose;
- char buffer[MAX_MAPPED_STRING_LENGTH];
- int bufsize = MAX_MAPPED_STRING_LENGTH;
- int charcount;
- bx_bool mouse_update;
- int y, height;
-
-
- XPointerMovedEvent *pointer_event;
- XEnterWindowEvent *enter_event;
- XLeaveWindowEvent *leave_event;
- XButtonEvent *button_event;
- XExposeEvent *expose_event;
-
-
- //current_x = -1;
- //current_y = -1;
- mouse_update = 0;
-
- while (XPending(bx_x_display) > 0) {
- XNextEvent(bx_x_display, &report);
- switch (report.type) {
-
- case Expose:
- expose_event = &report.xexpose;
- /* Adjust y, and reduce height if it overlaps headerbar. */
- y = expose_event->y - BX_HEADER_BAR_Y;
- height = expose_event->height;
- if (y < 0) {
- height += y;
- y = 0;
- }
-
- DEV_vga_redraw_area(
- (unsigned) expose_event->x,
- y,
- (unsigned) expose_event->width,
- height);
-
- /* Always draw headerbar, even if not touched by expose event.
- * As a small optimization, only do it on last contigous expose.
- */
- if (expose_event->count == 0) {
- show_headerbar();
- }
- break;
-
- case ConfigureNotify:
- BX_DEBUG(("ConfigureNotify Xevent"));
- /* FIXME: It's not clear why we have to show the headerbar here.
- * This should be forced by the following expose events.
- */
- show_headerbar();
- break;
-
- case ButtonPress:
- button_event = (XButtonEvent *) &report;
- BX_DEBUG(("xxx: buttonpress"));
- if (button_event->y < BX_HEADER_BAR_Y) {
- BX_DEBUG(("xxx: in headerbar"));
- if (mouse_update) {
- BX_DEBUG(("xxx: mouse_update=1"));
- send_keyboard_mouse_status();
- mouse_update = 0;
- }
- prev_x = current_x = -1;
- prev_y = current_y = -1;
- headerbar_click(button_event->x, button_event->y);
- break;
- }
- current_x = button_event->x;
- current_y = button_event->y;
- mouse_update = 1;
- BX_DEBUG(("xxx: x,y=(%d,%d)", current_x, current_y));
- switch (button_event->button) {
- case Button1:
- BX_DEBUG(("xxx: button1"));
- mouse_button_state |= 0x01;
- send_keyboard_mouse_status();
- mouse_update = 0;
- break;
- case Button2:
- BX_DEBUG(("XXX: button2"));
-
- // (mch) Hack for easier mouse handling (toggle mouse enable)
- toggle_mouse_enable();
-
- //mouse_button_state |= ;
- //send_keyboard_mouse_status();
- //mouse_update = 0;
- break;
- case Button3:
- BX_DEBUG(("xxx: button3"));
- mouse_button_state |= 0x02;
- send_keyboard_mouse_status();
- mouse_update = 0;
- break;
- }
- break;
-
- case ButtonRelease:
- button_event = (XButtonEvent *) &report;
-//BX_INFO(("xxx: buttonrelease"));
- if (button_event->y < BX_HEADER_BAR_Y) {
-//BX_INFO(("xxx: in headerbar"));
- if (mouse_update) {
-//BX_INFO(("xxx: mouse_update=1"));
- send_keyboard_mouse_status();
- mouse_update = 0;
- }
- prev_x = current_x = -1;
- prev_y = current_y = -1;
- // ignore, in headerbar area
- break;
- }
- current_x = button_event->x;
- current_y = button_event->y;
- mouse_update = 1;
-//BX_INFO(("xxx: x,y=(%d,%d)", current_x, current_y));
- switch (button_event->button) {
- case Button1:
-//BX_INFO(("xxx: button1"));
- mouse_button_state &= ~0x01;
- send_keyboard_mouse_status();
- mouse_update = 0;
- break;
- case Button2:
-//BX_INFO(("xxx: button2"));
- //mouse_button_state &= ~;
- //send_keyboard_mouse_status();
- //mouse_update = 0;
- break;
- case Button3:
-//BX_INFO(("xxx: button3"));
- mouse_button_state &= ~0x02;
- send_keyboard_mouse_status();
- mouse_update = 0;
- break;
- }
- break;
-
- case KeyPress:
- key_event = (XKeyEvent *) &report;
- charcount = XLookupString(key_event, buffer, bufsize, &keysym, &compose);
- xkeypress(keysym, 0);
- break;
-
- case KeyRelease:
- key_event = (XKeyEvent *) &report;
- charcount = XLookupString(key_event, buffer, bufsize, &keysym, &compose);
- xkeypress(keysym, 1);
- break;
-
- case MotionNotify:
- pointer_event = (XPointerMovedEvent *) &report;
- current_x = pointer_event->x;
- current_y = pointer_event->y;
- mouse_update = 1;
-//BX_INFO(("xxx: motionNotify x,y=(%d,%d)", current_x, current_y));
- break;
-
- case EnterNotify:
- enter_event = (XEnterWindowEvent *) &report;
- prev_x = current_x = enter_event->x;
- prev_y = current_y = enter_event->y;
-//BX_INFO(("xxx: enterNotify x,y=(%d,%d)", current_x, current_y));
- break;
-
- case LeaveNotify:
- leave_event = (XLeaveWindowEvent *) &report;
- prev_x = current_x = -1;
- prev_y = current_y = -1;
-//BX_INFO(("xxx: LeaveNotify x,y set to -1"));
- break;
-
- case MapNotify:
- /* screen needs redraw, since X would have tossed previous
- * requests before window mapped
- */
-//BX_INFO(("xxx: mapnotify: found"));
- //retval = 1;
- break;
-
- default:
- // (mch) Ignore...
- BX_DEBUG(("XXX: default Xevent type"));
- /* all events selected by StructureNotifyMask are thrown away here,
- * since nothing is done with them */
- break;
- } /* end switch */
- } /* end while */
-
- if (mouse_update) {
- BX_DEBUG(("XXX: bottom, send status"));
- send_keyboard_mouse_status();
- }
-}
-
-
- void
-send_keyboard_mouse_status(void)
-{
- BX_DEBUG(("XXX: prev=(%d,%d) curr=(%d,%d)",
- prev_x, prev_y, current_x, current_y));
-
- if ( (prev_x!=-1) && (current_x!=-1) && (prev_y!=-1) && (current_y!=-1)) {
- int dx, dy;
-
- // (mch) consider warping here
- dx = current_x - prev_x - warp_dx;
- dy = -(current_y - prev_y - warp_dy);
- warp_cursor(warp_home_x-current_x, warp_home_y-current_y);
-
-//BX_INFO(("xxx: MOUSE_MOTION: dx=%d, dy=%d", (int) dx, (int) dy));
- DEV_mouse_motion (dx, dy, mouse_button_state);
- //if (warped) {
- // prev_x = current_x = -1;
- // prev_y = current_y = -1;
- // }
- //else {
- prev_x = current_x;
- prev_y = current_y;
- // }
- }
- else {
- if ( (current_x!=-1) && (current_y!=-1)) {
- prev_x = current_x;
- prev_y = current_y;
- }
- else {
- prev_x = current_x = -1;
- prev_y = current_y = -1;
- }
- }
-}
-
- void
-bx_x_gui_c::flush(void)
-{
- if (bx_x_display)
- XFlush(bx_x_display);
-}
-
-
- void
-xkeypress(KeySym keysym, int press_release)
-{
- Bit32u key_event;
-
- /* Old (no mapping) behavior */
- if(!bx_options.keyboard.OuseMapping->get()){
-
- // this depends on the fact that the X11 keysyms which
- // correspond to the ascii characters space .. tilde
- // are in consequtive order.
- if ((keysym >= XK_space) && (keysym <= XK_asciitilde)) {
- key_event = ascii_to_key_event[keysym - XK_space];
- }
- else switch (keysym) {
- case XK_KP_1:
-#ifdef XK_KP_End
- case XK_KP_End:
-#endif
- key_event = BX_KEY_KP_END; break;
-
- case XK_KP_2:
-#ifdef XK_KP_Down
- case XK_KP_Down:
-#endif
- key_event = BX_KEY_KP_DOWN; break;
-
- case XK_KP_3:
-#ifdef XK_KP_Page_Down
- case XK_KP_Page_Down:
-#endif
- key_event = BX_KEY_KP_PAGE_DOWN; break;
-
- case XK_KP_4:
-#ifdef XK_KP_Left
- case XK_KP_Left:
-#endif
- key_event = BX_KEY_KP_LEFT; break;
-
- case XK_KP_5:
-#ifdef XK_KP_Begin
- case XK_KP_Begin:
-#endif
- key_event = BX_KEY_KP_5; break;
-
- case XK_KP_6:
-#ifdef XK_KP_Right
- case XK_KP_Right:
-#endif
- key_event = BX_KEY_KP_RIGHT; break;
-
- case XK_KP_7:
-#ifdef XK_KP_Home
- case XK_KP_Home:
-#endif
- key_event = BX_KEY_KP_HOME; break;
-
- case XK_KP_8:
-#ifdef XK_KP_Up
- case XK_KP_Up:
-#endif
- key_event = BX_KEY_KP_UP; break;
-
- case XK_KP_9:
-#ifdef XK_KP_Page_Up
- case XK_KP_Page_Up:
-#endif
- key_event = BX_KEY_KP_PAGE_UP; break;
-
- case XK_KP_0:
-#ifdef XK_KP_Insert
- case XK_KP_Insert:
-#endif
- key_event = BX_KEY_KP_INSERT; break;
-
- case XK_KP_Decimal:
-#ifdef XK_KP_Delete
- case XK_KP_Delete:
-#endif
- key_event = BX_KEY_KP_DELETE; break;
-
-#ifdef XK_KP_Enter
- case XK_KP_Enter: key_event = BX_KEY_KP_ENTER; break;
-#endif
-
- case XK_KP_Subtract: key_event = BX_KEY_KP_SUBTRACT; break;
- case XK_KP_Add: key_event = BX_KEY_KP_ADD; break;
-
- case XK_KP_Multiply: key_event = BX_KEY_KP_MULTIPLY; break;
- case XK_KP_Divide: key_event = BX_KEY_KP_DIVIDE; break;
-
-
- case XK_Up: key_event = BX_KEY_UP; break;
- case XK_Down: key_event = BX_KEY_DOWN; break;
- case XK_Left: key_event = BX_KEY_LEFT; break;
- case XK_Right: key_event = BX_KEY_RIGHT; break;
-
-
- case XK_Delete: key_event = BX_KEY_DELETE; break;
- case XK_BackSpace: key_event = BX_KEY_BACKSPACE; break;
- case XK_Tab: key_event = BX_KEY_TAB; break;
-#ifdef XK_ISO_Left_Tab
- case XK_ISO_Left_Tab: key_event = BX_KEY_TAB; break;
-#endif
- case XK_Return: key_event = BX_KEY_ENTER; break;
- case XK_Escape: key_event = BX_KEY_ESC; break;
- case XK_F1: key_event = BX_KEY_F1; break;
- case XK_F2: key_event = BX_KEY_F2; break;
- case XK_F3: key_event = BX_KEY_F3; break;
- case XK_F4: key_event = BX_KEY_F4; break;
- case XK_F5: key_event = BX_KEY_F5; break;
- case XK_F6: key_event = BX_KEY_F6; break;
- case XK_F7: key_event = BX_KEY_F7; break;
- case XK_F8: key_event = BX_KEY_F8; break;
- case XK_F9: key_event = BX_KEY_F9; break;
- case XK_F10: key_event = BX_KEY_F10; break;
- case XK_F11: key_event = BX_KEY_F11; break;
- case XK_F12: key_event = BX_KEY_F12; break;
- case XK_Control_L: key_event = BX_KEY_CTRL_L; break;
-#ifdef XK_Control_R
- case XK_Control_R: key_event = BX_KEY_CTRL_R; break;
-#endif
- case XK_Shift_L: key_event = BX_KEY_SHIFT_L; break;
- case XK_Shift_R: key_event = BX_KEY_SHIFT_R; break;
- case XK_Alt_L: key_event = BX_KEY_ALT_L; break;
-#ifdef XK_Alt_R
- case XK_Alt_R: key_event = BX_KEY_ALT_R; break;
-#endif
- case XK_Caps_Lock: key_event = BX_KEY_CAPS_LOCK; break;
- case XK_Num_Lock: key_event = BX_KEY_NUM_LOCK; break;
-#ifdef XK_Scroll_Lock
- case XK_Scroll_Lock: key_event = BX_KEY_SCRL_LOCK; break;
-#endif
-#ifdef XK_Print
- case XK_Print: key_event = BX_KEY_PRINT; break;
-#endif
-#ifdef XK_Pause
- case XK_Pause: key_event = BX_KEY_PAUSE; break;
-#endif
-
- case XK_Insert: key_event = BX_KEY_INSERT; break;
- case XK_Home: key_event = BX_KEY_HOME; break;
- case XK_End: key_event = BX_KEY_END; break;
- case XK_Page_Up: key_event = BX_KEY_PAGE_UP; break;
- case XK_Page_Down: key_event = BX_KEY_PAGE_DOWN; break;
-
- default:
- BX_ERROR(( "xkeypress(): keysym %x unhandled!", (unsigned) keysym ));
- return;
- break;
- }
- }
- else {
- /* use mapping */
- BXKeyEntry *entry = bx_keymap.findHostKey (keysym);
- if (!entry) {
- BX_ERROR(( "xkeypress(): keysym %x unhandled!", (unsigned) keysym ));
- return;
- }
- key_event = entry->baseKey;
- }
-
- if (press_release)
- key_event |= BX_KEY_RELEASED;
-
- DEV_kbd_gen_scancode(key_event);
-}
-
-
- void
-bx_x_gui_c::clear_screen(void)
-{
- XClearArea(bx_x_display, win, 0, bx_headerbar_y, dimension_x, dimension_y-bx_headerbar_y, 0);
-}
-
-
-
-
- void
-bx_x_gui_c::text_update(Bit8u *old_text, Bit8u *new_text,
- unsigned long cursor_x, unsigned long cursor_y,
- bx_vga_tminfo_t tm_info, unsigned nrows)
-{
- unsigned char *old_line, *new_line;
- unsigned char cChar;
- unsigned int curs, hchars, i, j, offset, rows, x, y, xc, yc, yc2;
- unsigned new_foreground, new_background;
- Bit8u cfwidth, cfheight, cfheight2, font_col, font_row, font_row2;
- bx_bool force_update=0;
- unsigned char cell[64];
-
- UNUSED(nrows);
- if (charmap_updated) {
- BX_INFO(("charmap update. Font Height is %d",font_height));
- for (unsigned c = 0; c<256; c++) {
- if (char_changed[c]) {
- XFreePixmap(bx_x_display, vgafont[c]);
- bx_bool gfxchar = tm_info.line_graphics && ((c & 0xE0) == 0xC0);
- j = 0;
- memset(cell, 0, sizeof(cell));
- for(i=0; i<font_height*2; i+=2) {
- cell[i] |= ((vga_charmap[(c<<5)+j] & 0x01)<<7);
- cell[i] |= ((vga_charmap[(c<<5)+j] & 0x02)<<5);
- cell[i] |= ((vga_charmap[(c<<5)+j] & 0x04)<<3);
- cell[i] |= ((vga_charmap[(c<<5)+j] & 0x08)<<1);
- cell[i] |= ((vga_charmap[(c<<5)+j] & 0x10)>>1);
- cell[i] |= ((vga_charmap[(c<<5)+j] & 0x20)>>3);
- cell[i] |= ((vga_charmap[(c<<5)+j] & 0x40)>>5);
- cell[i] |= ((vga_charmap[(c<<5)+j] & 0x80)>>7);
- if (gfxchar) {
- cell[i+1] = (vga_charmap[(c<<5)+j] & 0x01);
- }
- j++;
- }
-
- vgafont[c]=XCreateBitmapFromData(bx_x_display, win,
- (const char*)cell,
- font_width, font_height);
- if(vgafont[c] == None)
- BX_PANIC(("Can't create vga font [%d]", c));
- char_changed[c] = 0;
- }
- }
- force_update = 1;
- charmap_updated = 0;
- }
-
- if((tm_info.h_panning != h_panning) || (tm_info.v_panning != v_panning)) {
- force_update = 1;
- h_panning = tm_info.h_panning;
- v_panning = tm_info.v_panning;
- }
-
- // first invalidate character at previous and new cursor location
- if ( (prev_cursor_y < text_rows) && (prev_cursor_x < text_cols) ) {
- curs = prev_cursor_y * tm_info.line_offset + prev_cursor_x * 2;
- old_text[curs] = ~new_text[curs];
- }
- if((tm_info.cs_start <= tm_info.cs_end) && (tm_info.cs_start < font_height) &&
- (cursor_y < text_rows) && (cursor_x < text_cols)) {
- curs = cursor_y * tm_info.line_offset + cursor_x * 2;
- old_text[curs] = ~new_text[curs];
- } else {
- curs = 0xffff;
- }
-
- rows = text_rows;
- if (v_panning) rows++;
- y = 0;
- do {
- hchars = text_cols;
- if (h_panning) hchars++;
- if (v_panning) {
- if (y == 0) {
- yc = bx_headerbar_y;
- font_row = v_panning;
- cfheight = font_height - v_panning;
- } else {
- yc = y * font_height + bx_headerbar_y - v_panning;
- font_row = 0;
- if (rows == 1) {
- cfheight = v_panning;
- } else {
- cfheight = font_height;
- }
- }
- } else {
- yc = y * font_height + bx_headerbar_y;
- font_row = 0;
- cfheight = font_height;
- }
- new_line = new_text;
- old_line = old_text;
- x = 0;
- offset = y * tm_info.line_offset;
- do {
- if (h_panning) {
- if (hchars > text_cols) {
- xc = 0;
- font_col = h_panning;
- cfwidth = font_width - h_panning;
- } else {
- xc = x * font_width - h_panning;
- font_col = 0;
- if (hchars == 1) {
- cfwidth = h_panning;
- } else {
- cfwidth = font_width;
- }
- }
- } else {
- xc = x * font_width;
- font_col = 0;
- cfwidth = font_width;
- }
- if ( force_update || (old_text[0] != new_text[0])
- || (old_text[1] != new_text[1]) ) {
-
- cChar = new_text[0];
- new_foreground = new_text[1] & 0x0f;
- new_background = (new_text[1] & 0xf0) >> 4;
-
- XSetForeground(bx_x_display, gc, col_vals[DEV_vga_get_actl_pal_idx(new_foreground)]);
- XSetBackground(bx_x_display, gc, col_vals[DEV_vga_get_actl_pal_idx(new_background)]);
-
- XCopyPlane(bx_x_display, vgafont[cChar], win, gc, font_col, font_row, cfwidth, cfheight,
- xc, yc, 1);
- if (offset == curs) {
- XSetForeground(bx_x_display, gc, col_vals[DEV_vga_get_actl_pal_idx(new_background)]);
- XSetBackground(bx_x_display, gc, col_vals[DEV_vga_get_actl_pal_idx(new_foreground)]);
- if (font_row == 0) {
- yc2 = yc + tm_info.cs_start;
- font_row2 = tm_info.cs_start;
- cfheight2 = tm_info.cs_end - tm_info.cs_start + 1;
- } else {
- if (v_panning > tm_info.cs_start) {
- yc2 = yc;
- font_row2 = font_row;
- cfheight2 = tm_info.cs_end - v_panning + 1;
- } else {
- yc2 = yc + tm_info.cs_start - v_panning;
- font_row2 = tm_info.cs_start;
- cfheight2 = tm_info.cs_end - tm_info.cs_start + 1;
- }
- }
- XCopyPlane(bx_x_display, vgafont[cChar], win, gc, font_col, font_row2, cfwidth,
- cfheight2, xc, yc2, 1);
- }
- }
- x++;
- new_text+=2;
- old_text+=2;
- offset+=2;
- } while (--hchars);
- y++;
- new_text = new_line + tm_info.line_offset;
- old_text = old_line + tm_info.line_offset;
- } while (--rows);
-
- prev_cursor_x = cursor_x;
- prev_cursor_y = cursor_y;
-
- XFlush(bx_x_display);
-}
-
- int
-bx_x_gui_c::get_clipboard_text(Bit8u **bytes, Bit32s *nbytes)
-{
- int len;
- Bit8u *tmp = (Bit8u *)XFetchBytes (bx_x_display, &len);
- // according to man XFetchBytes, tmp must be freed by XFree(). So allocate
- // a new buffer with "new". The keyboard code will free it with delete []
- // when the paste is done.
- Bit8u *buf = new Bit8u[len];
- memcpy (buf, tmp, len);
- *bytes = buf;
- *nbytes = len;
- XFree (tmp);
- return 1;
-}
-
- int
-bx_x_gui_c::set_clipboard_text(char *text_snapshot, Bit32u len)
-{
- // this writes data to the clipboard.
- BX_INFO (("storing %d bytes to X windows clipboard", len));
- XSetSelectionOwner(bx_x_display, XA_PRIMARY, None, CurrentTime);
- XStoreBytes (bx_x_display, (char *)text_snapshot, len);
- return 1;
-}
-
-
- void
-bx_x_gui_c::graphics_tile_update(Bit8u *tile, unsigned x0, unsigned y0)
-{
- unsigned x, y;
- unsigned color, offset;
- Bit8u b0, b1, b2, b3;
-
- Bit16u *tile16 = (Bit16u *)tile;
- switch (vga_bpp) {
- case 32: // 32 bits per pixel
- if (ximage->byte_order == LSBFirst) {
- memcpy(&ximage->data[0], tile, x_tilesize*y_tilesize*4);
- }
- else { // MSBFirst
- for (y=0; y<y_tilesize; y++) {
- for (x=0; x<x_tilesize; x++) {
- offset = imWide*y + 4*x;
- ximage->data[offset + 0] = tile[(y*x_tilesize + x)*4 + 3];
- ximage->data[offset + 1] = tile[(y*x_tilesize + x)*4 + 2];
- ximage->data[offset + 2] = tile[(y*x_tilesize + x)*4 + 1];
- ximage->data[offset + 3] = tile[(y*x_tilesize + x)*4];
- }
- }
- }
- break;
- case 24: // 24 bits per pixel
- for (y=0; y<y_tilesize; y++) {
- for (x=0; x<x_tilesize; x++) {
- switch (imBPP) {
- case 24: // 24 bits per pixel
- offset = imWide*y + 3*x;
- if (ximage->byte_order == LSBFirst) {
- ximage->data[offset + 0] = tile[(y*x_tilesize + x)*3];
- ximage->data[offset + 1] = tile[(y*x_tilesize + x)*3 + 1];
- ximage->data[offset + 2] = tile[(y*x_tilesize + x)*3 + 2];
- }
- else { // MSBFirst
- ximage->data[offset + 0] = tile[(y*x_tilesize + x)*3 + 2];
- ximage->data[offset + 1] = tile[(y*x_tilesize + x)*3 + 1];
- ximage->data[offset + 2] = tile[(y*x_tilesize + x)*3];
- }
- break;
- case 32: // 32 bits per pixel
- offset = imWide*y + 4*x;
- if (ximage->byte_order == LSBFirst) {
- ximage->data[offset + 0] = tile[(y*x_tilesize + x)*3];
- ximage->data[offset + 1] = tile[(y*x_tilesize + x)*3 + 1];
- ximage->data[offset + 2] = tile[(y*x_tilesize + x)*3 + 2];
- ximage->data[offset + 3] = 0;
- }
- else { // MSBFirst
- ximage->data[offset + 0] = 0;
- ximage->data[offset + 1] = tile[(y*x_tilesize + x)*3 + 2];
- ximage->data[offset + 2] = tile[(y*x_tilesize + x)*3 + 1];
- ximage->data[offset + 3] = tile[(y*x_tilesize + x)*3];
- }
- break;
- }
- }
- }
- break;
- case 16: // 16 bits per pixel
- for (y=0; y<y_tilesize; y++) {
- for (x=0; x<x_tilesize; x++) {
- switch (imBPP) {
- case 16: // 16 bits per pixel
- offset = imWide*y + 2*x;
- if (ximage->byte_order == LSBFirst) {
- ximage->data[offset + 0] = tile[(y*x_tilesize + x)*2];
- ximage->data[offset + 1] = tile[(y*x_tilesize + x)*2 + 1];
- }
- else { // MSBFirst
- ximage->data[offset + 0] = tile[(y*x_tilesize + x)*2 + 1];
- ximage->data[offset + 1] = tile[(y*x_tilesize + x)*2];
- }
- break;
- case 24: // 24 bits per pixel
- offset = imWide*y + 3*x;
- b0 = (tile16[y*x_tilesize + x] & 0x001f) << 3;
- b1 = (tile16[y*x_tilesize + x] & 0x07e0) >> 3;
- b2 = (tile16[y*x_tilesize + x] & 0xF800) >> 8;
- if (ximage->byte_order == LSBFirst) {
- ximage->data[offset + 0] = b0;
- ximage->data[offset + 1] = b1;
- ximage->data[offset + 2] = b2;
- }
- else { // MSBFirst
- ximage->data[offset + 0] = b2;
- ximage->data[offset + 1] = b1;
- ximage->data[offset + 2] = b0;
- }
- break;
- case 32: // 32 bits per pixel
- offset = imWide*y + 4*x;
- b0 = (tile16[y*x_tilesize + x] & 0x001f) << 3;
- b1 = (tile16[y*x_tilesize + x] & 0x07e0) >> 3;
- b2 = (tile16[y*x_tilesize + x] & 0xF800) >> 8;
- if (ximage->byte_order == LSBFirst) {
- ximage->data[offset + 0] = b0;
- ximage->data[offset + 1] = b1;
- ximage->data[offset + 2] = b2;
- ximage->data[offset + 3] = 0;
- }
- else { // MSBFirst
- ximage->data[offset + 0] = 0;
- ximage->data[offset + 1] = b2;
- ximage->data[offset + 2] = b1;
- ximage->data[offset + 3] = b0;
- }
- break;
- }
- }
- }
- break;
- case 15: // 15 bits per pixel
- for (y=0; y<y_tilesize; y++) {
- for (x=0; x<x_tilesize; x++) {
- switch (imBPP) {
- case 16: // 16 bits per pixel
- offset = imWide*y + 2*x;
- b0 = (tile16[y*x_tilesize + x] & 0x001f);
- b0 |= (tile16[y*x_tilesize + x] & 0x0060) << 1;
- b1 = (tile16[y*x_tilesize + x] & 0x7f80) >> 7;
- if (ximage->byte_order == LSBFirst) {
- ximage->data[offset + 0] = b0;
- ximage->data[offset + 1] = b1;
- }
- else { // MSBFirst
- ximage->data[offset + 0] = b1;
- ximage->data[offset + 1] = b0;
- }
- break;
- case 24: // 24 bits per pixel
- offset = imWide*y + 3*x;
- b0 = (tile16[y*x_tilesize + x] & 0x001f) << 3;
- b1 = (tile16[y*x_tilesize + x] & 0x03e0) >> 2;
- b2 = (tile16[y*x_tilesize + x] & 0x7c00) >> 7;
- if (ximage->byte_order == LSBFirst) {
- ximage->data[offset + 0] = b0;
- ximage->data[offset + 1] = b1;
- ximage->data[offset + 2] = b2;
- }
- else { // MSBFirst
- ximage->data[offset + 0] = b2;
- ximage->data[offset + 1] = b1;
- ximage->data[offset + 2] = b0;
- }
- break;
- case 32: // 32 bits per pixel
- offset = imWide*y + 4*x;
- b0 = (tile16[y*x_tilesize + x] & 0x001f) << 3;
- b1 = (tile16[y*x_tilesize + x] & 0x03e0) >> 2;
- b2 = (tile16[y*x_tilesize + x] & 0x7c00) >> 7;
- if (ximage->byte_order == LSBFirst) {
- ximage->data[offset + 0] = b0;
- ximage->data[offset + 1] = b1;
- ximage->data[offset + 2] = b2;
- ximage->data[offset + 3] = 0;
- }
- else { // MSBFirst
- ximage->data[offset + 0] = 0;
- ximage->data[offset + 1] = b2;
- ximage->data[offset + 2] = b1;
- ximage->data[offset + 3] = b0;
- }
- break;
- }
- }
- }
- break;
- default: // 8 bits per pixel
- for (y=0; y<y_tilesize; y++) {
- for (x=0; x<x_tilesize; x++) {
- color = col_vals[tile[y*x_tilesize + x]];
- switch (imBPP) {
- case 8: // 8 bits per pixel
- ximage->data[imWide*y + x] = color;
- break;
- case 16: // 16 bits per pixel
- offset = imWide*y + 2*x;
- b0 = color >> 0;
- b1 = color >> 8;
- if (ximage->byte_order == LSBFirst) {
- ximage->data[offset + 0] = b0;
- ximage->data[offset + 1] = b1;
- }
- else { // MSBFirst
- ximage->data[offset + 0] = b1;
- ximage->data[offset + 1] = b0;
- }
- break;
- case 24: // 24 bits per pixel
- offset = imWide*y + 3*x;
- b0 = color >> 0;
- b1 = color >> 8;
- b2 = color >> 16;
- if (ximage->byte_order == LSBFirst) {
- ximage->data[offset + 0] = b0;
- ximage->data[offset + 1] = b1;
- ximage->data[offset + 2] = b2;
- }
- else { // MSBFirst
- ximage->data[offset + 0] = b2;
- ximage->data[offset + 1] = b1;
- ximage->data[offset + 2] = b0;
- }
- break;
- case 32: // 32 bits per pixel
- offset = imWide*y + 4*x;
- b0 = color >> 0;
- b1 = color >> 8;
- b2 = color >> 16;
- b3 = color >> 24;
- if (ximage->byte_order == LSBFirst) {
- ximage->data[offset + 0] = b0;
- ximage->data[offset + 1] = b1;
- ximage->data[offset + 2] = b2;
- ximage->data[offset + 3] = b3;
- }
- else { // MSBFirst
- ximage->data[offset + 0] = b3;
- ximage->data[offset + 1] = b2;
- ximage->data[offset + 2] = b1;
- ximage->data[offset + 3] = b0;
- }
- break;
- default:
- BX_PANIC(("X_graphics_tile_update: bits_per_pixel %u not implemented",
- (unsigned) imBPP));
- break;
- }
- }
- }
- }
- XPutImage(bx_x_display, win, gc, ximage, 0, 0, x0, y0+bx_headerbar_y,
- x_tilesize, y_tilesize);
-}
-
-
- bx_bool
-bx_x_gui_c::palette_change(unsigned index, unsigned red, unsigned green, unsigned blue)
-{
- // returns: 0=no screen update needed (color map change has direct effect)
- // 1=screen updated needed (redraw using current colormap)
- XColor color;
-
- color.flags = DoRed | DoGreen | DoBlue;
- color.red = red << 8;
- color.green = green << 8;
- color.blue = blue << 8;
-
- if (bx_options.Oprivate_colormap->get ()) {
- color.pixel = index;
- XStoreColor(bx_x_display, default_cmap, &color);
- return(0); // no screen update needed
- }
- else {
- XAllocColor(bx_x_display, DefaultColormap(bx_x_display, bx_x_screen_num),
- &color);
- col_vals[index] = color.pixel;
- return(1); // screen update needed
- }
-}
-
-
- void
-bx_x_gui_c::dimension_update(unsigned x, unsigned y, unsigned fheight, unsigned fwidth, unsigned bpp)
-{
- if ((bpp <= imBPP) && ((bpp == 8) || (bpp == 15) || (bpp == 16) || (bpp == 24) || (bpp == 32))) {
- vga_bpp = bpp;
- } else {
- BX_PANIC(("%d bpp graphics mode not supported", bpp));
- }
- if (fheight > 0) {
- font_height = fheight;
- font_width = fwidth;
- text_cols = x / font_width;
- text_rows = y / font_height;
- }
- if ( (x != dimension_x) || (y != (dimension_y-bx_headerbar_y)) ) {
- XSizeHints hints;
- long supplied_return;
-
- if ( XGetWMNormalHints(bx_x_display, win, &hints, &supplied_return) &&
- supplied_return & PMaxSize ) {
- hints.max_width = hints.min_width = x;
- hints.max_height = hints.min_height = y+bx_headerbar_y;
- XSetWMNormalHints(bx_x_display, win, &hints);
- }
- XResizeWindow(bx_x_display, win, x, y+bx_headerbar_y);
- dimension_x = x;
- dimension_y = y + bx_headerbar_y;
- }
-}
-
-
- void
-bx_x_gui_c::show_headerbar(void)
-{
- unsigned xorigin;
- int xleft, xright;
-
- // clear header bar area to white
- XFillRectangle(bx_x_display, win, gc_headerbar_inv, 0,0, dimension_x, bx_headerbar_y);
-
- xleft = 0;
- xright = dimension_x;
- for (unsigned i=0; i<bx_headerbar_entries; i++) {
- if (bx_headerbar_entry[i].alignment == BX_GRAVITY_LEFT) {
- xorigin = bx_headerbar_entry[i].xorigin;
- xleft += bx_headerbar_entry[i].xdim;
- }
- else {
- xorigin = dimension_x - bx_headerbar_entry[i].xorigin;
- xright = xorigin;
- }
- if (xright < xleft) break;
- XCopyPlane(bx_x_display, bx_headerbar_entry[i].bitmap, win, gc_headerbar,
- 0,0, bx_headerbar_entry[i].xdim, bx_headerbar_entry[i].ydim,
- xorigin, 0, 1);
- }
-}
-
-
- unsigned
-bx_x_gui_c::create_bitmap(const unsigned char *bmap, unsigned xdim, unsigned ydim)
-{
- if (bx_bitmap_entries >= BX_MAX_PIXMAPS) {
- BX_PANIC(("x: too many pixmaps, increase BX_MAX_PIXMAPS"));
- }
-
- bx_bitmaps[bx_bitmap_entries].bmap =
- XCreateBitmapFromData(bx_x_display, win, (const char *) bmap, xdim, ydim);
- bx_bitmaps[bx_bitmap_entries].xdim = xdim;
- bx_bitmaps[bx_bitmap_entries].ydim = ydim;
- if (!bx_bitmaps[bx_bitmap_entries].bmap) {
- BX_PANIC(("x: could not create bitmap"));
- }
- bx_bitmap_entries++;
- return(bx_bitmap_entries-1); // return index as handle
-}
-
-
- unsigned
-bx_x_gui_c::headerbar_bitmap(unsigned bmap_id, unsigned alignment, void (*f)(void))
-{
- unsigned hb_index;
-
- if ( (bx_headerbar_entries+1) > BX_MAX_HEADERBAR_ENTRIES )
- BX_PANIC(("x: too many headerbar entries, increase BX_MAX_HEADERBAR_ENTRIES"));
-
- bx_headerbar_entries++;
- hb_index = bx_headerbar_entries - 1;
-
- bx_headerbar_entry[hb_index].bitmap = bx_bitmaps[bmap_id].bmap;
- bx_headerbar_entry[hb_index].xdim = bx_bitmaps[bmap_id].xdim;
- bx_headerbar_entry[hb_index].ydim = bx_bitmaps[bmap_id].ydim;
- bx_headerbar_entry[hb_index].alignment = alignment;
- bx_headerbar_entry[hb_index].f = f;
- if (alignment == BX_GRAVITY_LEFT) {
- bx_headerbar_entry[hb_index].xorigin = bx_bitmap_left_xorigin;
- bx_headerbar_entry[hb_index].yorigin = 0;
- bx_bitmap_left_xorigin += bx_bitmaps[bmap_id].xdim;
- }
- else { // BX_GRAVITY_RIGHT
- bx_bitmap_right_xorigin += bx_bitmaps[bmap_id].xdim;
- bx_headerbar_entry[hb_index].xorigin = bx_bitmap_right_xorigin;
- bx_headerbar_entry[hb_index].yorigin = 0;
- }
- return(hb_index);
-}
-
- void
-bx_x_gui_c::replace_bitmap(unsigned hbar_id, unsigned bmap_id)
-{
- unsigned xorigin;
-
- bx_headerbar_entry[hbar_id].bitmap = bx_bitmaps[bmap_id].bmap;
-
- if (bx_headerbar_entry[hbar_id].alignment == BX_GRAVITY_LEFT)
- xorigin = bx_headerbar_entry[hbar_id].xorigin;
- else
- xorigin = dimension_x - bx_headerbar_entry[hbar_id].xorigin;
- XCopyPlane(bx_x_display, bx_headerbar_entry[hbar_id].bitmap, win, gc_headerbar,
- 0,0, bx_headerbar_entry[hbar_id].xdim, bx_headerbar_entry[hbar_id].ydim,
- xorigin, 0, 1);
-}
-
-
- void
-headerbar_click(int x, int y)
-{
- int xorigin;
-
- // assuming y is in bounds
- UNUSED(y);
- for (unsigned i=0; i<bx_headerbar_entries; i++) {
- if (bx_headerbar_entry[i].alignment == BX_GRAVITY_LEFT)
- xorigin = bx_headerbar_entry[i].xorigin;
- else
- xorigin = dimension_x - bx_headerbar_entry[i].xorigin;
- if ( (x>=xorigin) && (x<(xorigin+int(bx_headerbar_entry[i].xdim))) ) {
- bx_headerbar_entry[i].f();
- return;
- }
- }
-}
-
- void
-bx_x_gui_c::exit(void)
-{
- if (!x_init_done) return;
-
- // Delete the font bitmaps
- for (int i=0; i<256; i++) {
- //if (vgafont[i] != NULL)
- XFreePixmap(bx_x_display,vgafont[i]);
- }
-
- if (bx_x_display)
- XCloseDisplay (bx_x_display);
- BX_INFO(("Exit."));
-}
-
-static void warp_cursor (int dx, int dy)
-{
- if (bx_options.Omouse_enabled->get () &&
- (warp_dx || warp_dy || dx || dy)
- ) {
- warp_dx = dx;
- warp_dy = dy;
- XWarpPointer(bx_x_display, None, None, 0, 0, 0, 0, dx, dy);
- }
-}
-
-static void disable_cursor ()
-{
- static Cursor cursor;
- static unsigned cursor_created = 0;
-
- static int shape_width = 16,
- shape_height = 16,
- mask_width = 16,
- mask_height = 16;
-
- static uint32 shape_bits[(16*16)/32] = {
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- };
- static uint32 mask_bits[(16*16)/32] = {
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- 0x00000000, 0x00000000, 0x00000000, 0x00000000,
- };
-
- if (!cursor_created) {
- Pixmap shape, mask;
- XColor white, black;
- shape = XCreatePixmapFromBitmapData(bx_x_display,
- RootWindow(bx_x_display,bx_x_screen_num),
- (char*)shape_bits,
- shape_width,
- shape_height,
- 1, 0, 1);
- mask = XCreatePixmapFromBitmapData(bx_x_display,
- RootWindow(bx_x_display,bx_x_screen_num),
- (char*)mask_bits,
- mask_width,
- mask_height,
- 1, 0, 1);
- XParseColor(bx_x_display, default_cmap, "black", &black);
- XParseColor(bx_x_display, default_cmap, "white", &white);
- cursor = XCreatePixmapCursor(bx_x_display, shape, mask,
- &white, &black, 1, 1);
- cursor_created = 1;
- }
-
- XDefineCursor(bx_x_display, win, cursor);
-}
-
-static void enable_cursor ()
-{
- XUndefineCursor(bx_x_display, win);
-}
-
-/* convertStringToXKeysym is a keymap callback
- * used when reading the keymap file.
- * It converts a Symblic String to a GUI Constant
- *
- * It returns a Bit32u constant or BX_KEYMAP_UNKNOWN if it fails
- */
-static Bit32u convertStringToXKeysym (const char *string)
-{
- if (strncmp ("XK_", string, 3) != 0)
- return BX_KEYMAP_UNKNOWN;
- KeySym keysym=XStringToKeysym(string+3);
-
- // failure, return unknown
- if(keysym==NoSymbol) return BX_KEYMAP_UNKNOWN;
-
- return((Bit32u)keysym);
-}
-
-#if BX_USE_IDLE_HACK
-
-/* BX_USE_IDLE_HACK: a small idle hack by
- * Roland.Mainz@informatik.med.uni-giessen.de to prevent bochs
- * from consuming 100% CPU time even when it is not required (for
- * example, the OS in the emulator calls HLT to wait for an interupt)
- * pro:
- * - no more 100% CPU usage
- * contra:
- * - we're sleeping too long
- * - bochs still consumes ~10%-20% CPU time while executing an idle
- * linux kernel
- * - this is an hack
- */
-
-/* XPeekEvent() with timeout
- * (adopted from mozilla/gfx/src/xprint/xprintutil_printtofile.c#XNextEventTimeout())
- */
-static
-Bool XPeekEventTimeout( Display *display, XEvent *event_return, struct timeval *timeout )
-{
- int res;
- fd_set readfds;
- int display_fd = XConnectionNumber(display);
-
- /* small shortcut... */
- if( timeout == NULL )
- {
- XPeekEvent(display, event_return);
- return(True);
- }
-
- FD_ZERO(&readfds);
- FD_SET(display_fd, &readfds);
-
- /* Note/bug: In the case of internal X events (like used to trigger callbacks
- * registered by XpGetDocumentData()&co.) select() will return with "new info"
- * - but XNextEvent() below processes these _internal_ events silently - and
- * will block if there are no other non-internal events.
- * The workaround here is to check with XEventsQueued() if there are non-internal
- * events queued - if not select() will be called again - unfortunately we use
- * the old timeout here instead of the "remaining" time... (this only would hurt
- * if the timeout would be really long - but for current use with values below
- * 1/2 secs it does not hurt... =:-)
- */
- while( XEventsQueued(display, QueuedAfterFlush) == 0 )
- {
- res = select(display_fd+1, &readfds, NULL, NULL, timeout);
-
- switch(res)
- {
- case -1: /* select() error - should not happen */
- perror("XPeekEventTimeout: select() failure");
- return(False);
- case 0: /* timeout */
- return(False);
- }
- }
-
- XPeekEvent(display, event_return);
- return(True);
-}
-
-#if BX_USE_IDLE_HACK
-void bx_x_gui_c::sim_is_idle () {
- XEvent dummy;
- struct timeval timeout;
- timeout.tv_sec = 0;
- timeout.tv_usec = 1000; /* 1/1000 s */
- XPeekEventTimeout(bx_x_display, &dummy, &timeout);
-}
-#endif
-#endif /* BX_USE_IDLE_HACK */
-
-#endif /* if BX_WITH_X11 */
--- /dev/null
+/*
+ * QEMU ADB support
+ *
+ * Copyright (c) 2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+
+/* ADB commands */
+#define ADB_BUSRESET 0x00
+#define ADB_FLUSH 0x01
+#define ADB_WRITEREG 0x08
+#define ADB_READREG 0x0c
+
+/* ADB device commands */
+#define ADB_CMD_SELF_TEST 0xff
+#define ADB_CMD_CHANGE_ID 0xfe
+#define ADB_CMD_CHANGE_ID_AND_ACT 0xfd
+#define ADB_CMD_CHANGE_ID_AND_ENABLE 0x00
+
+/* ADB default device IDs (upper 4 bits of ADB command byte) */
+#define ADB_DONGLE 1
+#define ADB_KEYBOARD 2
+#define ADB_MOUSE 3
+#define ADB_TABLET 4
+#define ADB_MODEM 5
+#define ADB_MISC 7
+
+/* error codes */
+#define ADB_RET_NOTPRESENT (-2)
+
+int adb_request(ADBBusState *s, uint8_t *obuf, const uint8_t *buf, int len)
+{
+ ADBDevice *d;
+ int devaddr, cmd, i;
+
+ cmd = buf[0] & 0xf;
+ if (cmd == ADB_BUSRESET) {
+ for(i = 0; i < s->nb_devices; i++) {
+ d = &s->devices[i];
+ if (d->devreset) {
+ d->devreset(d);
+ }
+ }
+ return 0;
+ }
+ devaddr = buf[0] >> 4;
+ for(i = 0; i < s->nb_devices; i++) {
+ d = &s->devices[i];
+ if (d->devaddr == devaddr) {
+ return d->devreq(d, obuf, buf, len);
+ }
+ }
+ return ADB_RET_NOTPRESENT;
+}
+
+/* XXX: move that to cuda ? */
+int adb_poll(ADBBusState *s, uint8_t *obuf)
+{
+ ADBDevice *d;
+ int olen, i;
+ uint8_t buf[1];
+
+ olen = 0;
+ for(i = 0; i < s->nb_devices; i++) {
+ if (s->poll_index >= s->nb_devices)
+ s->poll_index = 0;
+ d = &s->devices[s->poll_index];
+ buf[0] = ADB_READREG | (d->devaddr << 4);
+ olen = adb_request(s, obuf + 1, buf, 1);
+ /* if there is data, we poll again the same device */
+ if (olen > 0) {
+ obuf[0] = buf[0];
+ olen++;
+ break;
+ }
+ s->poll_index++;
+ }
+ return olen;
+}
+
+ADBDevice *adb_register_device(ADBBusState *s, int devaddr,
+ ADBDeviceRequest *devreq,
+ ADBDeviceReset *devreset,
+ void *opaque)
+{
+ ADBDevice *d;
+ if (s->nb_devices >= MAX_ADB_DEVICES)
+ return NULL;
+ d = &s->devices[s->nb_devices++];
+ d->bus = s;
+ d->devaddr = devaddr;
+ d->devreq = devreq;
+ d->devreset = devreset;
+ d->opaque = opaque;
+ return d;
+}
+
+/***************************************************************/
+/* Keyboard ADB device */
+
+typedef struct KBDState {
+ uint8_t data[128];
+ int rptr, wptr, count;
+} KBDState;
+
+static const uint8_t pc_to_adb_keycode[256] = {
+ 0, 53, 18, 19, 20, 21, 23, 22, 26, 28, 25, 29, 27, 24, 51, 48,
+ 12, 13, 14, 15, 17, 16, 32, 34, 31, 35, 33, 30, 36, 54, 0, 1,
+ 2, 3, 5, 4, 38, 40, 37, 41, 39, 50, 56, 42, 6, 7, 8, 9,
+ 11, 45, 46, 43, 47, 44,123, 67, 58, 49, 57,122,120, 99,118, 96,
+ 97, 98,100,101,109, 71,107, 89, 91, 92, 78, 86, 87, 88, 69, 83,
+ 84, 85, 82, 65, 0, 0, 10,103,111, 0, 0,110, 81, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 94, 0, 93, 0, 0, 0, 0, 0, 0,104,102, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 76,125, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,105, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 75, 0, 0,124, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0,115, 62,116, 0, 59, 0, 60, 0,119,
+ 61,121,114,117, 0, 0, 0, 0, 0, 0, 0, 55,126, 0,127, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 95, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+static void adb_kbd_put_keycode(void *opaque, int keycode)
+{
+ ADBDevice *d = opaque;
+ KBDState *s = d->opaque;
+
+ if (s->count < sizeof(s->data)) {
+ s->data[s->wptr] = keycode;
+ if (++s->wptr == sizeof(s->data))
+ s->wptr = 0;
+ s->count++;
+ }
+}
+
+static int adb_kbd_poll(ADBDevice *d, uint8_t *obuf)
+{
+ static int ext_keycode;
+ KBDState *s = d->opaque;
+ int adb_keycode, keycode;
+ int olen;
+
+ olen = 0;
+ for(;;) {
+ if (s->count == 0)
+ break;
+ keycode = s->data[s->rptr];
+ if (++s->rptr == sizeof(s->data))
+ s->rptr = 0;
+ s->count--;
+
+ if (keycode == 0xe0) {
+ ext_keycode = 1;
+ } else {
+ if (ext_keycode)
+ adb_keycode = pc_to_adb_keycode[keycode | 0x80];
+ else
+ adb_keycode = pc_to_adb_keycode[keycode & 0x7f];
+ obuf[0] = adb_keycode | (keycode & 0x80);
+ /* NOTE: could put a second keycode if needed */
+ obuf[1] = 0xff;
+ olen = 2;
+ ext_keycode = 0;
+ break;
+ }
+ }
+ return olen;
+}
+
+static int adb_kbd_request(ADBDevice *d, uint8_t *obuf,
+ const uint8_t *buf, int len)
+{
+ KBDState *s = d->opaque;
+ int cmd, reg, olen;
+
+ if ((buf[0] & 0x0f) == ADB_FLUSH) {
+ /* flush keyboard fifo */
+ s->wptr = s->rptr = s->count = 0;
+ return 0;
+ }
+
+ cmd = buf[0] & 0xc;
+ reg = buf[0] & 0x3;
+ olen = 0;
+ switch(cmd) {
+ case ADB_WRITEREG:
+ switch(reg) {
+ case 2:
+ /* LED status */
+ break;
+ case 3:
+ switch(buf[2]) {
+ case ADB_CMD_SELF_TEST:
+ break;
+ case ADB_CMD_CHANGE_ID:
+ case ADB_CMD_CHANGE_ID_AND_ACT:
+ case ADB_CMD_CHANGE_ID_AND_ENABLE:
+ d->devaddr = buf[1] & 0xf;
+ break;
+ default:
+ /* XXX: check this */
+ d->devaddr = buf[1] & 0xf;
+ d->handler = buf[2];
+ break;
+ }
+ }
+ break;
+ case ADB_READREG:
+ switch(reg) {
+ case 0:
+ olen = adb_kbd_poll(d, obuf);
+ break;
+ case 1:
+ break;
+ case 2:
+ obuf[0] = 0x00; /* XXX: check this */
+ obuf[1] = 0x07; /* led status */
+ olen = 2;
+ break;
+ case 3:
+ obuf[0] = d->handler;
+ obuf[1] = d->devaddr;
+ olen = 2;
+ break;
+ }
+ break;
+ }
+ return olen;
+}
+
+void adb_kbd_init(ADBBusState *bus)
+{
+ ADBDevice *d;
+ KBDState *s;
+ s = qemu_mallocz(sizeof(KBDState));
+ d = adb_register_device(bus, ADB_KEYBOARD, adb_kbd_request, NULL, s);
+ d->handler = 1;
+ qemu_add_kbd_event_handler(adb_kbd_put_keycode, d);
+}
+
+/***************************************************************/
+/* Mouse ADB device */
+
+typedef struct MouseState {
+ int buttons_state, last_buttons_state;
+ int dx, dy, dz;
+} MouseState;
+
+static void adb_mouse_event(void *opaque,
+ int dx1, int dy1, int dz1, int buttons_state)
+{
+ ADBDevice *d = opaque;
+ MouseState *s = d->opaque;
+
+ s->dx += dx1;
+ s->dy += dy1;
+ s->dz += dz1;
+ s->buttons_state = buttons_state;
+}
+
+
+static int adb_mouse_poll(ADBDevice *d, uint8_t *obuf)
+{
+ MouseState *s = d->opaque;
+ int dx, dy;
+
+ if (s->last_buttons_state == s->buttons_state &&
+ s->dx == 0 && s->dy == 0)
+ return 0;
+
+ dx = s->dx;
+ if (dx < -63)
+ dx = -63;
+ else if (dx > 63)
+ dx = 63;
+
+ dy = s->dy;
+ if (dy < -63)
+ dy = -63;
+ else if (dy > 63)
+ dy = 63;
+
+ s->dx -= dx;
+ s->dy -= dy;
+ s->last_buttons_state = s->buttons_state;
+
+ dx &= 0x7f;
+ dy &= 0x7f;
+
+ if (!(s->buttons_state & MOUSE_EVENT_LBUTTON))
+ dy |= 0x80;
+ if (!(s->buttons_state & MOUSE_EVENT_RBUTTON))
+ dx |= 0x80;
+
+ obuf[0] = dy;
+ obuf[1] = dx;
+ return 2;
+}
+
+static int adb_mouse_request(ADBDevice *d, uint8_t *obuf,
+ const uint8_t *buf, int len)
+{
+ MouseState *s = d->opaque;
+ int cmd, reg, olen;
+
+ if ((buf[0] & 0x0f) == ADB_FLUSH) {
+ /* flush mouse fifo */
+ s->buttons_state = s->last_buttons_state;
+ s->dx = 0;
+ s->dy = 0;
+ s->dz = 0;
+ return 0;
+ }
+
+ cmd = buf[0] & 0xc;
+ reg = buf[0] & 0x3;
+ olen = 0;
+ switch(cmd) {
+ case ADB_WRITEREG:
+ switch(reg) {
+ case 2:
+ break;
+ case 3:
+ switch(buf[2]) {
+ case ADB_CMD_SELF_TEST:
+ break;
+ case ADB_CMD_CHANGE_ID:
+ case ADB_CMD_CHANGE_ID_AND_ACT:
+ case ADB_CMD_CHANGE_ID_AND_ENABLE:
+ d->devaddr = buf[1] & 0xf;
+ break;
+ default:
+ /* XXX: check this */
+ d->devaddr = buf[1] & 0xf;
+ break;
+ }
+ }
+ break;
+ case ADB_READREG:
+ switch(reg) {
+ case 0:
+ olen = adb_mouse_poll(d, obuf);
+ break;
+ case 1:
+ break;
+ case 3:
+ obuf[0] = d->handler;
+ obuf[1] = d->devaddr;
+ olen = 2;
+ break;
+ }
+ break;
+ }
+ return olen;
+}
+
+void adb_mouse_init(ADBBusState *bus)
+{
+ ADBDevice *d;
+ MouseState *s;
+
+ s = qemu_mallocz(sizeof(MouseState));
+ d = adb_register_device(bus, ADB_MOUSE, adb_mouse_request, NULL, s);
+ d->handler = 2;
+ qemu_add_mouse_event_handler(adb_mouse_event, d);
+}
--- /dev/null
+/*
+ * QEMU Adlib emulation
+ *
+ * Copyright (c) 2004 Vassili Karpov (malc)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+
+#define dolog(...) AUD_log ("adlib", __VA_ARGS__)
+#ifdef DEBUG
+#define ldebug(...) dolog (__VA_ARGS__)
+#else
+#define ldebug(...)
+#endif
+
+#ifdef USE_YMF262
+#define HAS_YMF262 1
+#include "ymf262.h"
+void YMF262UpdateOneQEMU(int which, INT16 *dst, int length);
+#define SHIFT 2
+#else
+#include "fmopl.h"
+#define SHIFT 1
+#endif
+
+#ifdef _WIN32
+#include <windows.h>
+#define small_delay() Sleep (1)
+#else
+#define small_delay() usleep (1)
+#endif
+
+#define IO_READ_PROTO(name) \
+ uint32_t name (void *opaque, uint32_t nport)
+#define IO_WRITE_PROTO(name) \
+ void name (void *opaque, uint32_t nport, uint32_t val)
+
+static struct {
+ int port;
+ int freq;
+} conf = {0x220, 44100};
+
+typedef struct {
+ int enabled;
+ int active;
+ int cparam;
+ int64_t ticks;
+ int bufpos;
+ int16_t *mixbuf;
+ double interval;
+ QEMUTimer *ts, *opl_ts;
+ SWVoice *voice;
+ int left, pos, samples, bytes_per_second, old_free;
+ int refcount;
+#ifndef USE_YMF262
+ FM_OPL *opl;
+#endif
+} AdlibState;
+
+static AdlibState adlib;
+
+static IO_WRITE_PROTO(adlib_write)
+{
+ AdlibState *s = opaque;
+ int a = nport & 3;
+ int status;
+
+ s->ticks = qemu_get_clock (vm_clock);
+ s->active = 1;
+ AUD_enable (s->voice, 1);
+
+#ifdef USE_YMF262
+ status = YMF262Write (0, a, val);
+#else
+ status = OPLWrite (s->opl, a, val);
+#endif
+}
+
+static IO_READ_PROTO(adlib_read)
+{
+ AdlibState *s = opaque;
+ uint8_t data;
+ int a = nport & 3;
+
+#ifdef USE_YMF262
+ (void) s;
+ data = YMF262Read (0, a);
+#else
+ data = OPLRead (s->opl, a);
+#endif
+ return data;
+}
+
+static void OPL_timer (void *opaque)
+{
+ AdlibState *s = opaque;
+#ifdef USE_YMF262
+ YMF262TimerOver (s->cparam >> 1, s->cparam & 1);
+#else
+ OPLTimerOver (s->opl, s->cparam);
+#endif
+ qemu_mod_timer (s->opl_ts, qemu_get_clock (vm_clock) + s->interval);
+}
+
+static void YMF262TimerHandler (int c, double interval_Sec)
+{
+ AdlibState *s = &adlib;
+ if (interval_Sec == 0.0) {
+ qemu_del_timer (s->opl_ts);
+ return;
+ }
+ s->cparam = c;
+ s->interval = ticks_per_sec * interval_Sec;
+ qemu_mod_timer (s->opl_ts, qemu_get_clock (vm_clock) + s->interval);
+ small_delay ();
+}
+
+static int write_audio (AdlibState *s, int samples)
+{
+ int net = 0;
+ int ss = samples;
+ while (samples) {
+ int nbytes = samples << SHIFT;
+ int wbytes = AUD_write (s->voice,
+ s->mixbuf + (s->pos << (SHIFT - 1)),
+ nbytes);
+ int wsampl = wbytes >> SHIFT;
+ samples -= wsampl;
+ s->pos = (s->pos + wsampl) % s->samples;
+ net += wsampl;
+ if (!wbytes)
+ break;
+ }
+ if (net > ss) {
+ dolog ("WARNING: net > ss\n");
+ }
+ return net;
+}
+
+static void timer (void *opaque)
+{
+ AdlibState *s = opaque;
+ int elapsed, samples, net = 0;
+
+ if (s->refcount)
+ dolog ("refcount=%d\n", s->refcount);
+
+ s->refcount += 1;
+ if (!(s->active && s->enabled))
+ goto reset;
+
+ AUD_run ();
+
+ while (s->left) {
+ int written = write_audio (s, s->left);
+ net += written;
+ if (!written)
+ goto reset2;
+ s->left -= written;
+ }
+ s->pos = 0;
+
+ elapsed = AUD_calc_elapsed (s->voice);
+ if (!elapsed)
+ goto reset2;
+
+ /* elapsed = AUD_get_free (s->voice); */
+ samples = elapsed >> SHIFT;
+ if (!samples)
+ goto reset2;
+
+ samples = audio_MIN (samples, s->samples - s->pos);
+ if (s->left)
+ dolog ("left=%d samples=%d elapsed=%d free=%d\n",
+ s->left, samples, elapsed, AUD_get_free (s->voice));
+
+ if (!samples)
+ goto reset2;
+
+#ifdef USE_YMF262
+ YMF262UpdateOneQEMU (0, s->mixbuf + s->pos * 2, samples);
+#else
+ YM3812UpdateOne (s->opl, s->mixbuf + s->pos, samples);
+#endif
+
+ while (samples) {
+ int written = write_audio (s, samples);
+ net += written;
+ if (!written)
+ break;
+ samples -= written;
+ }
+ if (!samples)
+ s->pos = 0;
+ s->left = samples;
+
+reset2:
+ AUD_adjust (s->voice, net << SHIFT);
+reset:
+ qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + ticks_per_sec / 1024);
+ s->refcount -= 1;
+}
+
+static void Adlib_fini (AdlibState *s)
+{
+#ifdef USE_YMF262
+ YMF262Shutdown ();
+#else
+ if (s->opl) {
+ OPLDestroy (s->opl);
+ s->opl = NULL;
+ }
+#endif
+
+ if (s->opl_ts)
+ qemu_free_timer (s->opl_ts);
+
+ if (s->ts)
+ qemu_free_timer (s->ts);
+
+#define maybe_free(p) if (p) qemu_free (p)
+ maybe_free (s->mixbuf);
+#undef maybe_free
+
+ s->active = 0;
+ s->enabled = 0;
+}
+
+void Adlib_init (void)
+{
+ AdlibState *s = &adlib;
+
+ memset (s, 0, sizeof (*s));
+
+#ifdef USE_YMF262
+ if (YMF262Init (1, 14318180, conf.freq)) {
+ dolog ("YMF262Init %d failed\n", conf.freq);
+ return;
+ }
+ else {
+ YMF262SetTimerHandler (0, YMF262TimerHandler, 0);
+ s->enabled = 1;
+ }
+#else
+ s->opl = OPLCreate (OPL_TYPE_YM3812, 3579545, conf.freq);
+ if (!s->opl) {
+ dolog ("OPLCreate %d failed\n", conf.freq);
+ return;
+ }
+ else {
+ OPLSetTimerHandler (s->opl, YMF262TimerHandler, 0);
+ s->enabled = 1;
+ }
+#endif
+
+ s->opl_ts = qemu_new_timer (vm_clock, OPL_timer, s);
+ if (!s->opl_ts) {
+ dolog ("Can not get timer for adlib emulation\n");
+ Adlib_fini (s);
+ return;
+ }
+
+ s->ts = qemu_new_timer (vm_clock, timer, s);
+ if (!s->opl_ts) {
+ dolog ("Can not get timer for adlib emulation\n");
+ Adlib_fini (s);
+ return;
+ }
+
+ s->voice = AUD_open (s->voice, "adlib", conf.freq, SHIFT, AUD_FMT_S16);
+ if (!s->voice) {
+ Adlib_fini (s);
+ return;
+ }
+
+ s->bytes_per_second = conf.freq << SHIFT;
+ s->samples = AUD_get_buffer_size (s->voice) >> SHIFT;
+ s->mixbuf = qemu_mallocz (s->samples << SHIFT);
+
+ if (!s->mixbuf) {
+ dolog ("not enough memory for adlib mixing buffer (%d)\n",
+ s->samples << SHIFT);
+ Adlib_fini (s);
+ return;
+ }
+ register_ioport_read (0x388, 4, 1, adlib_read, s);
+ register_ioport_write (0x388, 4, 1, adlib_write, s);
+
+ register_ioport_read (conf.port, 4, 1, adlib_read, s);
+ register_ioport_write (conf.port, 4, 1, adlib_write, s);
+
+ register_ioport_read (conf.port + 8, 2, 1, adlib_read, s);
+ register_ioport_write (conf.port + 8, 2, 1, adlib_write, s);
+
+ qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + 1);
+}
--- /dev/null
+/*
+ * QEMU Cirrus CLGD 54xx VGA Emulator.
+ *
+ * Copyright (c) 2004 Fabrice Bellard
+ * Copyright (c) 2004 Makoto Suzuki (suzu)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+/*
+ * Reference: Finn Thogersons' VGADOC4b
+ * available at http://home.worldonline.dk/~finth/
+ */
+#include "vl.h"
+#include "vga_int.h"
+
+/*
+ * TODO:
+ * - add support for WRITEMASK (GR2F)
+ * - optimize linear mappings
+ * - optimize bitblt functions
+ */
+
+//#define DEBUG_CIRRUS
+//#define DEBUG_BITBLT
+
+/***************************************
+ *
+ * definitions
+ *
+ ***************************************/
+
+#define qemu_MIN(a,b) ((a) < (b) ? (a) : (b))
+
+// ID
+#define CIRRUS_ID_CLGD5422 (0x23<<2)
+#define CIRRUS_ID_CLGD5426 (0x24<<2)
+#define CIRRUS_ID_CLGD5424 (0x25<<2)
+#define CIRRUS_ID_CLGD5428 (0x26<<2)
+#define CIRRUS_ID_CLGD5430 (0x28<<2)
+#define CIRRUS_ID_CLGD5434 (0x2A<<2)
+#define CIRRUS_ID_CLGD5436 (0x2B<<2)
+#define CIRRUS_ID_CLGD5446 (0x2E<<2)
+
+// sequencer 0x07
+#define CIRRUS_SR7_BPP_VGA 0x00
+#define CIRRUS_SR7_BPP_SVGA 0x01
+#define CIRRUS_SR7_BPP_MASK 0x0e
+#define CIRRUS_SR7_BPP_8 0x00
+#define CIRRUS_SR7_BPP_16_DOUBLEVCLK 0x02
+#define CIRRUS_SR7_BPP_24 0x04
+#define CIRRUS_SR7_BPP_16 0x06
+#define CIRRUS_SR7_BPP_32 0x08
+#define CIRRUS_SR7_ISAADDR_MASK 0xe0
+
+// sequencer 0x0f
+#define CIRRUS_MEMSIZE_512k 0x08
+#define CIRRUS_MEMSIZE_1M 0x10
+#define CIRRUS_MEMSIZE_2M 0x18
+#define CIRRUS_MEMFLAGS_BANKSWITCH 0x80 // bank switching is enabled.
+
+// sequencer 0x12
+#define CIRRUS_CURSOR_SHOW 0x01
+#define CIRRUS_CURSOR_HIDDENPEL 0x02
+#define CIRRUS_CURSOR_LARGE 0x04 // 64x64 if set, 32x32 if clear
+
+// sequencer 0x17
+#define CIRRUS_BUSTYPE_VLBFAST 0x10
+#define CIRRUS_BUSTYPE_PCI 0x20
+#define CIRRUS_BUSTYPE_VLBSLOW 0x30
+#define CIRRUS_BUSTYPE_ISA 0x38
+#define CIRRUS_MMIO_ENABLE 0x04
+#define CIRRUS_MMIO_USE_PCIADDR 0x40 // 0xb8000 if cleared.
+#define CIRRUS_MEMSIZEEXT_DOUBLE 0x80
+
+// control 0x0b
+#define CIRRUS_BANKING_DUAL 0x01
+#define CIRRUS_BANKING_GRANULARITY_16K 0x20 // set:16k, clear:4k
+
+// control 0x30
+#define CIRRUS_BLTMODE_BACKWARDS 0x01
+#define CIRRUS_BLTMODE_MEMSYSDEST 0x02
+#define CIRRUS_BLTMODE_MEMSYSSRC 0x04
+#define CIRRUS_BLTMODE_TRANSPARENTCOMP 0x08
+#define CIRRUS_BLTMODE_PATTERNCOPY 0x40
+#define CIRRUS_BLTMODE_COLOREXPAND 0x80
+#define CIRRUS_BLTMODE_PIXELWIDTHMASK 0x30
+#define CIRRUS_BLTMODE_PIXELWIDTH8 0x00
+#define CIRRUS_BLTMODE_PIXELWIDTH16 0x10
+#define CIRRUS_BLTMODE_PIXELWIDTH24 0x20
+#define CIRRUS_BLTMODE_PIXELWIDTH32 0x30
+
+// control 0x31
+#define CIRRUS_BLT_BUSY 0x01
+#define CIRRUS_BLT_START 0x02
+#define CIRRUS_BLT_RESET 0x04
+#define CIRRUS_BLT_FIFOUSED 0x10
+#define CIRRUS_BLT_AUTOSTART 0x80
+
+// control 0x32
+#define CIRRUS_ROP_0 0x00
+#define CIRRUS_ROP_SRC_AND_DST 0x05
+#define CIRRUS_ROP_NOP 0x06
+#define CIRRUS_ROP_SRC_AND_NOTDST 0x09
+#define CIRRUS_ROP_NOTDST 0x0b
+#define CIRRUS_ROP_SRC 0x0d
+#define CIRRUS_ROP_1 0x0e
+#define CIRRUS_ROP_NOTSRC_AND_DST 0x50
+#define CIRRUS_ROP_SRC_XOR_DST 0x59
+#define CIRRUS_ROP_SRC_OR_DST 0x6d
+#define CIRRUS_ROP_NOTSRC_OR_NOTDST 0x90
+#define CIRRUS_ROP_SRC_NOTXOR_DST 0x95
+#define CIRRUS_ROP_SRC_OR_NOTDST 0xad
+#define CIRRUS_ROP_NOTSRC 0xd0
+#define CIRRUS_ROP_NOTSRC_OR_DST 0xd6
+#define CIRRUS_ROP_NOTSRC_AND_NOTDST 0xda
+
+#define CIRRUS_ROP_NOP_INDEX 2
+#define CIRRUS_ROP_SRC_INDEX 5
+
+// control 0x33
+#define CIRRUS_BLTMODEEXT_SOLIDFILL 0x04
+#define CIRRUS_BLTMODEEXT_COLOREXPINV 0x02
+#define CIRRUS_BLTMODEEXT_DWORDGRANULARITY 0x01
+
+// memory-mapped IO
+#define CIRRUS_MMIO_BLTBGCOLOR 0x00 // dword
+#define CIRRUS_MMIO_BLTFGCOLOR 0x04 // dword
+#define CIRRUS_MMIO_BLTWIDTH 0x08 // word
+#define CIRRUS_MMIO_BLTHEIGHT 0x0a // word
+#define CIRRUS_MMIO_BLTDESTPITCH 0x0c // word
+#define CIRRUS_MMIO_BLTSRCPITCH 0x0e // word
+#define CIRRUS_MMIO_BLTDESTADDR 0x10 // dword
+#define CIRRUS_MMIO_BLTSRCADDR 0x14 // dword
+#define CIRRUS_MMIO_BLTWRITEMASK 0x17 // byte
+#define CIRRUS_MMIO_BLTMODE 0x18 // byte
+#define CIRRUS_MMIO_BLTROP 0x1a // byte
+#define CIRRUS_MMIO_BLTMODEEXT 0x1b // byte
+#define CIRRUS_MMIO_BLTTRANSPARENTCOLOR 0x1c // word?
+#define CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK 0x20 // word?
+#define CIRRUS_MMIO_LINEARDRAW_START_X 0x24 // word
+#define CIRRUS_MMIO_LINEARDRAW_START_Y 0x26 // word
+#define CIRRUS_MMIO_LINEARDRAW_END_X 0x28 // word
+#define CIRRUS_MMIO_LINEARDRAW_END_Y 0x2a // word
+#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_INC 0x2c // byte
+#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_ROLLOVER 0x2d // byte
+#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_MASK 0x2e // byte
+#define CIRRUS_MMIO_LINEARDRAW_LINESTYLE_ACCUM 0x2f // byte
+#define CIRRUS_MMIO_BRESENHAM_K1 0x30 // word
+#define CIRRUS_MMIO_BRESENHAM_K3 0x32 // word
+#define CIRRUS_MMIO_BRESENHAM_ERROR 0x34 // word
+#define CIRRUS_MMIO_BRESENHAM_DELTA_MAJOR 0x36 // word
+#define CIRRUS_MMIO_BRESENHAM_DIRECTION 0x38 // byte
+#define CIRRUS_MMIO_LINEDRAW_MODE 0x39 // byte
+#define CIRRUS_MMIO_BLTSTATUS 0x40 // byte
+
+// PCI 0x00: vendor, 0x02: device
+#define PCI_VENDOR_CIRRUS 0x1013
+#define PCI_DEVICE_CLGD5462 0x00d0
+#define PCI_DEVICE_CLGD5465 0x00d6
+
+// PCI 0x04: command(word), 0x06(word): status
+#define PCI_COMMAND_IOACCESS 0x0001
+#define PCI_COMMAND_MEMACCESS 0x0002
+#define PCI_COMMAND_BUSMASTER 0x0004
+#define PCI_COMMAND_SPECIALCYCLE 0x0008
+#define PCI_COMMAND_MEMWRITEINVALID 0x0010
+#define PCI_COMMAND_PALETTESNOOPING 0x0020
+#define PCI_COMMAND_PARITYDETECTION 0x0040
+#define PCI_COMMAND_ADDRESSDATASTEPPING 0x0080
+#define PCI_COMMAND_SERR 0x0100
+#define PCI_COMMAND_BACKTOBACKTRANS 0x0200
+// PCI 0x08, 0xff000000 (0x09-0x0b:class,0x08:rev)
+#define PCI_CLASS_BASE_DISPLAY 0x03
+// PCI 0x08, 0x00ff0000
+#define PCI_CLASS_SUB_VGA 0x00
+// PCI 0x0c, 0x00ff0000 (0x0c:cacheline,0x0d:latency,0x0e:headertype,0x0f:Built-in self test)
+#define PCI_CLASS_HEADERTYPE_00h 0x00
+// 0x10-0x3f (headertype 00h)
+// PCI 0x10,0x14,0x18,0x1c,0x20,0x24: base address mapping registers
+// 0x10: MEMBASE, 0x14: IOBASE(hard-coded in XFree86 3.x)
+#define PCI_MAP_MEM 0x0
+#define PCI_MAP_IO 0x1
+#define PCI_MAP_MEM_ADDR_MASK (~0xf)
+#define PCI_MAP_IO_ADDR_MASK (~0x3)
+#define PCI_MAP_MEMFLAGS_32BIT 0x0
+#define PCI_MAP_MEMFLAGS_32BIT_1M 0x1
+#define PCI_MAP_MEMFLAGS_64BIT 0x4
+#define PCI_MAP_MEMFLAGS_CACHEABLE 0x8
+// PCI 0x28: cardbus CIS pointer
+// PCI 0x2c: subsystem vendor id, 0x2e: subsystem id
+// PCI 0x30: expansion ROM base address
+#define PCI_ROMBIOS_ENABLED 0x1
+// PCI 0x34: 0xffffff00=reserved, 0x000000ff=capabilities pointer
+// PCI 0x38: reserved
+// PCI 0x3c: 0x3c=int-line, 0x3d=int-pin, 0x3e=min-gnt, 0x3f=maax-lat
+
+#define CIRRUS_PNPMMIO_SIZE 0x1000
+
+
+/* I/O and memory hook */
+#define CIRRUS_HOOK_NOT_HANDLED 0
+#define CIRRUS_HOOK_HANDLED 1
+
+struct CirrusVGAState;
+typedef void (*cirrus_bitblt_rop_t) (struct CirrusVGAState *s,
+ uint8_t * dst, const uint8_t * src,
+ int dstpitch, int srcpitch,
+ int bltwidth, int bltheight);
+typedef void (*cirrus_fill_t)(struct CirrusVGAState *s,
+ uint8_t *dst, int dst_pitch, int width, int height);
+
+typedef struct CirrusVGAState {
+ VGA_STATE_COMMON
+
+ int cirrus_linear_io_addr;
+ int cirrus_linear_bitblt_io_addr;
+ int cirrus_mmio_io_addr;
+ uint32_t cirrus_addr_mask;
+ uint32_t linear_mmio_mask;
+ uint8_t cirrus_shadow_gr0;
+ uint8_t cirrus_shadow_gr1;
+ uint8_t cirrus_hidden_dac_lockindex;
+ uint8_t cirrus_hidden_dac_data;
+ uint32_t cirrus_bank_base[2];
+ uint32_t cirrus_bank_limit[2];
+ uint8_t cirrus_hidden_palette[48];
+ uint32_t hw_cursor_x;
+ uint32_t hw_cursor_y;
+ int cirrus_blt_pixelwidth;
+ int cirrus_blt_width;
+ int cirrus_blt_height;
+ int cirrus_blt_dstpitch;
+ int cirrus_blt_srcpitch;
+ uint32_t cirrus_blt_fgcol;
+ uint32_t cirrus_blt_bgcol;
+ uint32_t cirrus_blt_dstaddr;
+ uint32_t cirrus_blt_srcaddr;
+ uint8_t cirrus_blt_mode;
+ uint8_t cirrus_blt_modeext;
+ cirrus_bitblt_rop_t cirrus_rop;
+#define CIRRUS_BLTBUFSIZE (2048 * 4) /* one line width */
+ uint8_t cirrus_bltbuf[CIRRUS_BLTBUFSIZE];
+ uint8_t *cirrus_srcptr;
+ uint8_t *cirrus_srcptr_end;
+ uint32_t cirrus_srccounter;
+ /* hwcursor display state */
+ int last_hw_cursor_size;
+ int last_hw_cursor_x;
+ int last_hw_cursor_y;
+ int last_hw_cursor_y_start;
+ int last_hw_cursor_y_end;
+ int real_vram_size; /* XXX: suppress that */
+ CPUWriteMemoryFunc **cirrus_linear_write;
+} CirrusVGAState;
+
+typedef struct PCICirrusVGAState {
+ PCIDevice dev;
+ CirrusVGAState cirrus_vga;
+} PCICirrusVGAState;
+
+static uint8_t rop_to_index[256];
+
+/***************************************
+ *
+ * prototypes.
+ *
+ ***************************************/
+
+
+static void cirrus_bitblt_reset(CirrusVGAState *s);
+static void cirrus_update_memory_access(CirrusVGAState *s);
+
+/***************************************
+ *
+ * raster operations
+ *
+ ***************************************/
+
+static void cirrus_bitblt_rop_nop(CirrusVGAState *s,
+ uint8_t *dst,const uint8_t *src,
+ int dstpitch,int srcpitch,
+ int bltwidth,int bltheight)
+{
+}
+
+static void cirrus_bitblt_fill_nop(CirrusVGAState *s,
+ uint8_t *dst,
+ int dstpitch, int bltwidth,int bltheight)
+{
+}
+
+#define ROP_NAME 0
+#define ROP_OP(d, s) d = 0
+#include "cirrus_vga_rop.h"
+
+#define ROP_NAME src_and_dst
+#define ROP_OP(d, s) d = (s) & (d)
+#include "cirrus_vga_rop.h"
+
+#define ROP_NAME src_and_notdst
+#define ROP_OP(d, s) d = (s) & (~(d))
+#include "cirrus_vga_rop.h"
+
+#define ROP_NAME notdst
+#define ROP_OP(d, s) d = ~(d)
+#include "cirrus_vga_rop.h"
+
+#define ROP_NAME src
+#define ROP_OP(d, s) d = s
+#include "cirrus_vga_rop.h"
+
+#define ROP_NAME 1
+#define ROP_OP(d, s) d = ~0
+#include "cirrus_vga_rop.h"
+
+#define ROP_NAME notsrc_and_dst
+#define ROP_OP(d, s) d = (~(s)) & (d)
+#include "cirrus_vga_rop.h"
+
+#define ROP_NAME src_xor_dst
+#define ROP_OP(d, s) d = (s) ^ (d)
+#include "cirrus_vga_rop.h"
+
+#define ROP_NAME src_or_dst
+#define ROP_OP(d, s) d = (s) | (d)
+#include "cirrus_vga_rop.h"
+
+#define ROP_NAME notsrc_or_notdst
+#define ROP_OP(d, s) d = (~(s)) | (~(d))
+#include "cirrus_vga_rop.h"
+
+#define ROP_NAME src_notxor_dst
+#define ROP_OP(d, s) d = ~((s) ^ (d))
+#include "cirrus_vga_rop.h"
+
+#define ROP_NAME src_or_notdst
+#define ROP_OP(d, s) d = (s) | (~(d))
+#include "cirrus_vga_rop.h"
+
+#define ROP_NAME notsrc
+#define ROP_OP(d, s) d = (~(s))
+#include "cirrus_vga_rop.h"
+
+#define ROP_NAME notsrc_or_dst
+#define ROP_OP(d, s) d = (~(s)) | (d)
+#include "cirrus_vga_rop.h"
+
+#define ROP_NAME notsrc_and_notdst
+#define ROP_OP(d, s) d = (~(s)) & (~(d))
+#include "cirrus_vga_rop.h"
+
+static const cirrus_bitblt_rop_t cirrus_fwd_rop[16] = {
+ cirrus_bitblt_rop_fwd_0,
+ cirrus_bitblt_rop_fwd_src_and_dst,
+ cirrus_bitblt_rop_nop,
+ cirrus_bitblt_rop_fwd_src_and_notdst,
+ cirrus_bitblt_rop_fwd_notdst,
+ cirrus_bitblt_rop_fwd_src,
+ cirrus_bitblt_rop_fwd_1,
+ cirrus_bitblt_rop_fwd_notsrc_and_dst,
+ cirrus_bitblt_rop_fwd_src_xor_dst,
+ cirrus_bitblt_rop_fwd_src_or_dst,
+ cirrus_bitblt_rop_fwd_notsrc_or_notdst,
+ cirrus_bitblt_rop_fwd_src_notxor_dst,
+ cirrus_bitblt_rop_fwd_src_or_notdst,
+ cirrus_bitblt_rop_fwd_notsrc,
+ cirrus_bitblt_rop_fwd_notsrc_or_dst,
+ cirrus_bitblt_rop_fwd_notsrc_and_notdst,
+};
+
+static const cirrus_bitblt_rop_t cirrus_bkwd_rop[16] = {
+ cirrus_bitblt_rop_bkwd_0,
+ cirrus_bitblt_rop_bkwd_src_and_dst,
+ cirrus_bitblt_rop_nop,
+ cirrus_bitblt_rop_bkwd_src_and_notdst,
+ cirrus_bitblt_rop_bkwd_notdst,
+ cirrus_bitblt_rop_bkwd_src,
+ cirrus_bitblt_rop_bkwd_1,
+ cirrus_bitblt_rop_bkwd_notsrc_and_dst,
+ cirrus_bitblt_rop_bkwd_src_xor_dst,
+ cirrus_bitblt_rop_bkwd_src_or_dst,
+ cirrus_bitblt_rop_bkwd_notsrc_or_notdst,
+ cirrus_bitblt_rop_bkwd_src_notxor_dst,
+ cirrus_bitblt_rop_bkwd_src_or_notdst,
+ cirrus_bitblt_rop_bkwd_notsrc,
+ cirrus_bitblt_rop_bkwd_notsrc_or_dst,
+ cirrus_bitblt_rop_bkwd_notsrc_and_notdst,
+};
+
+#define ROP2(name) {\
+ name ## _8,\
+ name ## _16,\
+ name ## _24,\
+ name ## _32,\
+ }
+
+#define ROP_NOP2(func) {\
+ func,\
+ func,\
+ func,\
+ func,\
+ }
+
+static const cirrus_bitblt_rop_t cirrus_patternfill[16][4] = {
+ ROP2(cirrus_patternfill_0),
+ ROP2(cirrus_patternfill_src_and_dst),
+ ROP_NOP2(cirrus_bitblt_rop_nop),
+ ROP2(cirrus_patternfill_src_and_notdst),
+ ROP2(cirrus_patternfill_notdst),
+ ROP2(cirrus_patternfill_src),
+ ROP2(cirrus_patternfill_1),
+ ROP2(cirrus_patternfill_notsrc_and_dst),
+ ROP2(cirrus_patternfill_src_xor_dst),
+ ROP2(cirrus_patternfill_src_or_dst),
+ ROP2(cirrus_patternfill_notsrc_or_notdst),
+ ROP2(cirrus_patternfill_src_notxor_dst),
+ ROP2(cirrus_patternfill_src_or_notdst),
+ ROP2(cirrus_patternfill_notsrc),
+ ROP2(cirrus_patternfill_notsrc_or_dst),
+ ROP2(cirrus_patternfill_notsrc_and_notdst),
+};
+
+static const cirrus_bitblt_rop_t cirrus_colorexpand_transp[16][4] = {
+ ROP2(cirrus_colorexpand_transp_0),
+ ROP2(cirrus_colorexpand_transp_src_and_dst),
+ ROP_NOP2(cirrus_bitblt_rop_nop),
+ ROP2(cirrus_colorexpand_transp_src_and_notdst),
+ ROP2(cirrus_colorexpand_transp_notdst),
+ ROP2(cirrus_colorexpand_transp_src),
+ ROP2(cirrus_colorexpand_transp_1),
+ ROP2(cirrus_colorexpand_transp_notsrc_and_dst),
+ ROP2(cirrus_colorexpand_transp_src_xor_dst),
+ ROP2(cirrus_colorexpand_transp_src_or_dst),
+ ROP2(cirrus_colorexpand_transp_notsrc_or_notdst),
+ ROP2(cirrus_colorexpand_transp_src_notxor_dst),
+ ROP2(cirrus_colorexpand_transp_src_or_notdst),
+ ROP2(cirrus_colorexpand_transp_notsrc),
+ ROP2(cirrus_colorexpand_transp_notsrc_or_dst),
+ ROP2(cirrus_colorexpand_transp_notsrc_and_notdst),
+};
+
+static const cirrus_bitblt_rop_t cirrus_colorexpand[16][4] = {
+ ROP2(cirrus_colorexpand_0),
+ ROP2(cirrus_colorexpand_src_and_dst),
+ ROP_NOP2(cirrus_bitblt_rop_nop),
+ ROP2(cirrus_colorexpand_src_and_notdst),
+ ROP2(cirrus_colorexpand_notdst),
+ ROP2(cirrus_colorexpand_src),
+ ROP2(cirrus_colorexpand_1),
+ ROP2(cirrus_colorexpand_notsrc_and_dst),
+ ROP2(cirrus_colorexpand_src_xor_dst),
+ ROP2(cirrus_colorexpand_src_or_dst),
+ ROP2(cirrus_colorexpand_notsrc_or_notdst),
+ ROP2(cirrus_colorexpand_src_notxor_dst),
+ ROP2(cirrus_colorexpand_src_or_notdst),
+ ROP2(cirrus_colorexpand_notsrc),
+ ROP2(cirrus_colorexpand_notsrc_or_dst),
+ ROP2(cirrus_colorexpand_notsrc_and_notdst),
+};
+
+static const cirrus_bitblt_rop_t cirrus_colorexpand_pattern_transp[16][4] = {
+ ROP2(cirrus_colorexpand_pattern_transp_0),
+ ROP2(cirrus_colorexpand_pattern_transp_src_and_dst),
+ ROP_NOP2(cirrus_bitblt_rop_nop),
+ ROP2(cirrus_colorexpand_pattern_transp_src_and_notdst),
+ ROP2(cirrus_colorexpand_pattern_transp_notdst),
+ ROP2(cirrus_colorexpand_pattern_transp_src),
+ ROP2(cirrus_colorexpand_pattern_transp_1),
+ ROP2(cirrus_colorexpand_pattern_transp_notsrc_and_dst),
+ ROP2(cirrus_colorexpand_pattern_transp_src_xor_dst),
+ ROP2(cirrus_colorexpand_pattern_transp_src_or_dst),
+ ROP2(cirrus_colorexpand_pattern_transp_notsrc_or_notdst),
+ ROP2(cirrus_colorexpand_pattern_transp_src_notxor_dst),
+ ROP2(cirrus_colorexpand_pattern_transp_src_or_notdst),
+ ROP2(cirrus_colorexpand_pattern_transp_notsrc),
+ ROP2(cirrus_colorexpand_pattern_transp_notsrc_or_dst),
+ ROP2(cirrus_colorexpand_pattern_transp_notsrc_and_notdst),
+};
+
+static const cirrus_bitblt_rop_t cirrus_colorexpand_pattern[16][4] = {
+ ROP2(cirrus_colorexpand_pattern_0),
+ ROP2(cirrus_colorexpand_pattern_src_and_dst),
+ ROP_NOP2(cirrus_bitblt_rop_nop),
+ ROP2(cirrus_colorexpand_pattern_src_and_notdst),
+ ROP2(cirrus_colorexpand_pattern_notdst),
+ ROP2(cirrus_colorexpand_pattern_src),
+ ROP2(cirrus_colorexpand_pattern_1),
+ ROP2(cirrus_colorexpand_pattern_notsrc_and_dst),
+ ROP2(cirrus_colorexpand_pattern_src_xor_dst),
+ ROP2(cirrus_colorexpand_pattern_src_or_dst),
+ ROP2(cirrus_colorexpand_pattern_notsrc_or_notdst),
+ ROP2(cirrus_colorexpand_pattern_src_notxor_dst),
+ ROP2(cirrus_colorexpand_pattern_src_or_notdst),
+ ROP2(cirrus_colorexpand_pattern_notsrc),
+ ROP2(cirrus_colorexpand_pattern_notsrc_or_dst),
+ ROP2(cirrus_colorexpand_pattern_notsrc_and_notdst),
+};
+
+static const cirrus_fill_t cirrus_fill[16][4] = {
+ ROP2(cirrus_fill_0),
+ ROP2(cirrus_fill_src_and_dst),
+ ROP_NOP2(cirrus_bitblt_fill_nop),
+ ROP2(cirrus_fill_src_and_notdst),
+ ROP2(cirrus_fill_notdst),
+ ROP2(cirrus_fill_src),
+ ROP2(cirrus_fill_1),
+ ROP2(cirrus_fill_notsrc_and_dst),
+ ROP2(cirrus_fill_src_xor_dst),
+ ROP2(cirrus_fill_src_or_dst),
+ ROP2(cirrus_fill_notsrc_or_notdst),
+ ROP2(cirrus_fill_src_notxor_dst),
+ ROP2(cirrus_fill_src_or_notdst),
+ ROP2(cirrus_fill_notsrc),
+ ROP2(cirrus_fill_notsrc_or_dst),
+ ROP2(cirrus_fill_notsrc_and_notdst),
+};
+
+static inline void cirrus_bitblt_fgcol(CirrusVGAState *s)
+{
+ unsigned int color;
+ switch (s->cirrus_blt_pixelwidth) {
+ case 1:
+ s->cirrus_blt_fgcol = s->cirrus_shadow_gr1;
+ break;
+ case 2:
+ color = s->cirrus_shadow_gr1 | (s->gr[0x11] << 8);
+ s->cirrus_blt_fgcol = le16_to_cpu(color);
+ break;
+ case 3:
+ s->cirrus_blt_fgcol = s->cirrus_shadow_gr1 |
+ (s->gr[0x11] << 8) | (s->gr[0x13] << 16);
+ break;
+ default:
+ case 4:
+ color = s->cirrus_shadow_gr1 | (s->gr[0x11] << 8) |
+ (s->gr[0x13] << 16) | (s->gr[0x15] << 24);
+ s->cirrus_blt_fgcol = le32_to_cpu(color);
+ break;
+ }
+}
+
+static inline void cirrus_bitblt_bgcol(CirrusVGAState *s)
+{
+ unsigned int color;
+ switch (s->cirrus_blt_pixelwidth) {
+ case 1:
+ s->cirrus_blt_bgcol = s->cirrus_shadow_gr0;
+ break;
+ case 2:
+ color = s->cirrus_shadow_gr0 | (s->gr[0x10] << 8);
+ s->cirrus_blt_bgcol = le16_to_cpu(color);
+ break;
+ case 3:
+ s->cirrus_blt_bgcol = s->cirrus_shadow_gr0 |
+ (s->gr[0x10] << 8) | (s->gr[0x12] << 16);
+ break;
+ default:
+ case 4:
+ color = s->cirrus_shadow_gr0 | (s->gr[0x10] << 8) |
+ (s->gr[0x12] << 16) | (s->gr[0x14] << 24);
+ s->cirrus_blt_bgcol = le32_to_cpu(color);
+ break;
+ }
+}
+
+static void cirrus_invalidate_region(CirrusVGAState * s, int off_begin,
+ int off_pitch, int bytesperline,
+ int lines)
+{
+ int y;
+ int off_cur;
+ int off_cur_end;
+
+ for (y = 0; y < lines; y++) {
+ off_cur = off_begin;
+ off_cur_end = off_cur + bytesperline;
+ off_cur &= TARGET_PAGE_MASK;
+ while (off_cur < off_cur_end) {
+ cpu_physical_memory_set_dirty(s->vram_offset + off_cur);
+ off_cur += TARGET_PAGE_SIZE;
+ }
+ off_begin += off_pitch;
+ }
+}
+
+static int cirrus_bitblt_common_patterncopy(CirrusVGAState * s,
+ const uint8_t * src)
+{
+ uint8_t *dst;
+
+ dst = s->vram_ptr + s->cirrus_blt_dstaddr;
+ (*s->cirrus_rop) (s, dst, src,
+ s->cirrus_blt_dstpitch, 0,
+ s->cirrus_blt_width, s->cirrus_blt_height);
+ cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
+ s->cirrus_blt_dstpitch, s->cirrus_blt_width,
+ s->cirrus_blt_height);
+ return 1;
+}
+
+/* fill */
+
+static int cirrus_bitblt_solidfill(CirrusVGAState *s, int blt_rop)
+{
+ cirrus_fill_t rop_func;
+
+ rop_func = cirrus_fill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
+ rop_func(s, s->vram_ptr + s->cirrus_blt_dstaddr,
+ s->cirrus_blt_dstpitch,
+ s->cirrus_blt_width, s->cirrus_blt_height);
+ cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
+ s->cirrus_blt_dstpitch, s->cirrus_blt_width,
+ s->cirrus_blt_height);
+ cirrus_bitblt_reset(s);
+ return 1;
+}
+
+/***************************************
+ *
+ * bitblt (video-to-video)
+ *
+ ***************************************/
+
+static int cirrus_bitblt_videotovideo_patterncopy(CirrusVGAState * s)
+{
+ return cirrus_bitblt_common_patterncopy(s,
+ s->vram_ptr +
+ (s->cirrus_blt_srcaddr & ~7));
+}
+
+static int cirrus_bitblt_videotovideo_copy(CirrusVGAState * s)
+{
+ (*s->cirrus_rop) (s, s->vram_ptr + s->cirrus_blt_dstaddr,
+ s->vram_ptr + s->cirrus_blt_srcaddr,
+ s->cirrus_blt_dstpitch, s->cirrus_blt_srcpitch,
+ s->cirrus_blt_width, s->cirrus_blt_height);
+ cirrus_invalidate_region(s, s->cirrus_blt_dstaddr,
+ s->cirrus_blt_dstpitch, s->cirrus_blt_width,
+ s->cirrus_blt_height);
+ return 1;
+}
+
+/***************************************
+ *
+ * bitblt (cpu-to-video)
+ *
+ ***************************************/
+
+static void cirrus_bitblt_cputovideo_next(CirrusVGAState * s)
+{
+ int copy_count;
+ uint8_t *end_ptr;
+
+ if (s->cirrus_srccounter > 0) {
+ if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) {
+ cirrus_bitblt_common_patterncopy(s, s->cirrus_bltbuf);
+ the_end:
+ s->cirrus_srccounter = 0;
+ cirrus_bitblt_reset(s);
+ } else {
+ /* at least one scan line */
+ do {
+ (*s->cirrus_rop)(s, s->vram_ptr + s->cirrus_blt_dstaddr,
+ s->cirrus_bltbuf, 0, 0, s->cirrus_blt_width, 1);
+ cirrus_invalidate_region(s, s->cirrus_blt_dstaddr, 0,
+ s->cirrus_blt_width, 1);
+ s->cirrus_blt_dstaddr += s->cirrus_blt_dstpitch;
+ s->cirrus_srccounter -= s->cirrus_blt_srcpitch;
+ if (s->cirrus_srccounter <= 0)
+ goto the_end;
+ /* more bytes than needed can be transfered because of
+ word alignment, so we keep them for the next line */
+ /* XXX: keep alignment to speed up transfer */
+ end_ptr = s->cirrus_bltbuf + s->cirrus_blt_srcpitch;
+ copy_count = s->cirrus_srcptr_end - end_ptr;
+ memmove(s->cirrus_bltbuf, end_ptr, copy_count);
+ s->cirrus_srcptr = s->cirrus_bltbuf + copy_count;
+ s->cirrus_srcptr_end = s->cirrus_bltbuf + s->cirrus_blt_srcpitch;
+ } while (s->cirrus_srcptr >= s->cirrus_srcptr_end);
+ }
+ }
+}
+
+/***************************************
+ *
+ * bitblt wrapper
+ *
+ ***************************************/
+
+static void cirrus_bitblt_reset(CirrusVGAState * s)
+{
+ s->gr[0x31] &=
+ ~(CIRRUS_BLT_START | CIRRUS_BLT_BUSY | CIRRUS_BLT_FIFOUSED);
+ s->cirrus_srcptr = &s->cirrus_bltbuf[0];
+ s->cirrus_srcptr_end = &s->cirrus_bltbuf[0];
+ s->cirrus_srccounter = 0;
+ cirrus_update_memory_access(s);
+}
+
+static int cirrus_bitblt_cputovideo(CirrusVGAState * s)
+{
+ int w;
+
+ s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_MEMSYSSRC;
+ s->cirrus_srcptr = &s->cirrus_bltbuf[0];
+ s->cirrus_srcptr_end = &s->cirrus_bltbuf[0];
+
+ if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) {
+ if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) {
+ s->cirrus_blt_srcpitch = 8;
+ } else {
+ /* XXX: check for 24 bpp */
+ s->cirrus_blt_srcpitch = 8 * 8 * s->cirrus_blt_pixelwidth;
+ }
+ s->cirrus_srccounter = s->cirrus_blt_srcpitch;
+ } else {
+ if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) {
+ w = s->cirrus_blt_width / s->cirrus_blt_pixelwidth;
+ if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_DWORDGRANULARITY)
+ s->cirrus_blt_srcpitch = ((w + 31) >> 5);
+ else
+ s->cirrus_blt_srcpitch = ((w + 7) >> 3);
+ } else {
+ s->cirrus_blt_srcpitch = s->cirrus_blt_width;
+ }
+ s->cirrus_srccounter = s->cirrus_blt_srcpitch * s->cirrus_blt_height;
+ }
+ s->cirrus_srcptr = s->cirrus_bltbuf;
+ s->cirrus_srcptr_end = s->cirrus_bltbuf + s->cirrus_blt_srcpitch;
+ cirrus_update_memory_access(s);
+ return 1;
+}
+
+static int cirrus_bitblt_videotocpu(CirrusVGAState * s)
+{
+ /* XXX */
+#ifdef DEBUG_BITBLT
+ printf("cirrus: bitblt (video to cpu) is not implemented yet\n");
+#endif
+ return 0;
+}
+
+static int cirrus_bitblt_videotovideo(CirrusVGAState * s)
+{
+ int ret;
+
+ if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) {
+ ret = cirrus_bitblt_videotovideo_patterncopy(s);
+ } else {
+ ret = cirrus_bitblt_videotovideo_copy(s);
+ }
+ if (ret)
+ cirrus_bitblt_reset(s);
+ return ret;
+}
+
+static void cirrus_bitblt_start(CirrusVGAState * s)
+{
+ uint8_t blt_rop;
+
+ s->gr[0x31] |= CIRRUS_BLT_BUSY;
+
+ s->cirrus_blt_width = (s->gr[0x20] | (s->gr[0x21] << 8)) + 1;
+ s->cirrus_blt_height = (s->gr[0x22] | (s->gr[0x23] << 8)) + 1;
+ s->cirrus_blt_dstpitch = (s->gr[0x24] | (s->gr[0x25] << 8));
+ s->cirrus_blt_srcpitch = (s->gr[0x26] | (s->gr[0x27] << 8));
+ s->cirrus_blt_dstaddr =
+ (s->gr[0x28] | (s->gr[0x29] << 8) | (s->gr[0x2a] << 16));
+ s->cirrus_blt_srcaddr =
+ (s->gr[0x2c] | (s->gr[0x2d] << 8) | (s->gr[0x2e] << 16));
+ s->cirrus_blt_mode = s->gr[0x30];
+ s->cirrus_blt_modeext = s->gr[0x33];
+ blt_rop = s->gr[0x32];
+
+#ifdef DEBUG_BITBLT
+ printf("rop=0x%02x mode=0x%02x modeext=0x%02x w=%d h=%d dpitch=%d spicth=%d daddr=0x%08x saddr=0x%08x writemask=0x%02x\n",
+ blt_rop,
+ s->cirrus_blt_mode,
+ s->cirrus_blt_modeext,
+ s->cirrus_blt_width,
+ s->cirrus_blt_height,
+ s->cirrus_blt_dstpitch,
+ s->cirrus_blt_srcpitch,
+ s->cirrus_blt_dstaddr,
+ s->cirrus_blt_srcaddr,
+ s->sr[0x2f]);
+#endif
+
+ switch (s->cirrus_blt_mode & CIRRUS_BLTMODE_PIXELWIDTHMASK) {
+ case CIRRUS_BLTMODE_PIXELWIDTH8:
+ s->cirrus_blt_pixelwidth = 1;
+ break;
+ case CIRRUS_BLTMODE_PIXELWIDTH16:
+ s->cirrus_blt_pixelwidth = 2;
+ break;
+ case CIRRUS_BLTMODE_PIXELWIDTH24:
+ s->cirrus_blt_pixelwidth = 3;
+ break;
+ case CIRRUS_BLTMODE_PIXELWIDTH32:
+ s->cirrus_blt_pixelwidth = 4;
+ break;
+ default:
+#ifdef DEBUG_BITBLT
+ printf("cirrus: bitblt - pixel width is unknown\n");
+#endif
+ goto bitblt_ignore;
+ }
+ s->cirrus_blt_mode &= ~CIRRUS_BLTMODE_PIXELWIDTHMASK;
+
+ if ((s->
+ cirrus_blt_mode & (CIRRUS_BLTMODE_MEMSYSSRC |
+ CIRRUS_BLTMODE_MEMSYSDEST))
+ == (CIRRUS_BLTMODE_MEMSYSSRC | CIRRUS_BLTMODE_MEMSYSDEST)) {
+#ifdef DEBUG_BITBLT
+ printf("cirrus: bitblt - memory-to-memory copy is requested\n");
+#endif
+ goto bitblt_ignore;
+ }
+
+ if ((s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_SOLIDFILL) &&
+ (s->cirrus_blt_mode & (CIRRUS_BLTMODE_MEMSYSDEST |
+ CIRRUS_BLTMODE_TRANSPARENTCOMP |
+ CIRRUS_BLTMODE_PATTERNCOPY |
+ CIRRUS_BLTMODE_COLOREXPAND)) ==
+ (CIRRUS_BLTMODE_PATTERNCOPY | CIRRUS_BLTMODE_COLOREXPAND)) {
+ cirrus_bitblt_fgcol(s);
+ cirrus_bitblt_solidfill(s, blt_rop);
+ } else {
+ if ((s->cirrus_blt_mode & (CIRRUS_BLTMODE_COLOREXPAND |
+ CIRRUS_BLTMODE_PATTERNCOPY)) ==
+ CIRRUS_BLTMODE_COLOREXPAND) {
+
+ if (s->cirrus_blt_mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) {
+ if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV)
+ cirrus_bitblt_bgcol(s);
+ else
+ cirrus_bitblt_fgcol(s);
+ s->cirrus_rop = cirrus_colorexpand_transp[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
+ } else {
+ cirrus_bitblt_fgcol(s);
+ cirrus_bitblt_bgcol(s);
+ s->cirrus_rop = cirrus_colorexpand[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
+ }
+ } else if (s->cirrus_blt_mode & CIRRUS_BLTMODE_PATTERNCOPY) {
+ if (s->cirrus_blt_mode & CIRRUS_BLTMODE_COLOREXPAND) {
+ if (s->cirrus_blt_mode & CIRRUS_BLTMODE_TRANSPARENTCOMP) {
+ if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV)
+ cirrus_bitblt_bgcol(s);
+ else
+ cirrus_bitblt_fgcol(s);
+ s->cirrus_rop = cirrus_colorexpand_pattern_transp[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
+ } else {
+ cirrus_bitblt_fgcol(s);
+ cirrus_bitblt_bgcol(s);
+ s->cirrus_rop = cirrus_colorexpand_pattern[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
+ }
+ } else {
+ s->cirrus_rop = cirrus_patternfill[rop_to_index[blt_rop]][s->cirrus_blt_pixelwidth - 1];
+ }
+ } else {
+ if (s->cirrus_blt_mode & CIRRUS_BLTMODE_BACKWARDS) {
+ s->cirrus_blt_dstpitch = -s->cirrus_blt_dstpitch;
+ s->cirrus_blt_srcpitch = -s->cirrus_blt_srcpitch;
+ s->cirrus_rop = cirrus_bkwd_rop[rop_to_index[blt_rop]];
+ } else {
+ s->cirrus_rop = cirrus_fwd_rop[rop_to_index[blt_rop]];
+ }
+ }
+
+ // setup bitblt engine.
+ if (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSSRC) {
+ if (!cirrus_bitblt_cputovideo(s))
+ goto bitblt_ignore;
+ } else if (s->cirrus_blt_mode & CIRRUS_BLTMODE_MEMSYSDEST) {
+ if (!cirrus_bitblt_videotocpu(s))
+ goto bitblt_ignore;
+ } else {
+ if (!cirrus_bitblt_videotovideo(s))
+ goto bitblt_ignore;
+ }
+ }
+ return;
+ bitblt_ignore:;
+ cirrus_bitblt_reset(s);
+}
+
+static void cirrus_write_bitblt(CirrusVGAState * s, unsigned reg_value)
+{
+ unsigned old_value;
+
+ old_value = s->gr[0x31];
+ s->gr[0x31] = reg_value;
+
+ if (((old_value & CIRRUS_BLT_RESET) != 0) &&
+ ((reg_value & CIRRUS_BLT_RESET) == 0)) {
+ cirrus_bitblt_reset(s);
+ } else if (((old_value & CIRRUS_BLT_START) == 0) &&
+ ((reg_value & CIRRUS_BLT_START) != 0)) {
+ cirrus_bitblt_start(s);
+ }
+}
+
+
+/***************************************
+ *
+ * basic parameters
+ *
+ ***************************************/
+
+static void cirrus_get_offsets(VGAState *s1,
+ uint32_t *pline_offset,
+ uint32_t *pstart_addr)
+{
+ CirrusVGAState * s = (CirrusVGAState *)s1;
+ uint32_t start_addr;
+ uint32_t line_offset;
+
+ line_offset = s->cr[0x13]
+ | ((s->cr[0x1b] & 0x10) << 4);
+ line_offset <<= 3;
+ *pline_offset = line_offset;
+
+ start_addr = (s->cr[0x0c] << 8)
+ | s->cr[0x0d]
+ | ((s->cr[0x1b] & 0x01) << 16)
+ | ((s->cr[0x1b] & 0x0c) << 15)
+ | ((s->cr[0x1d] & 0x80) << 12);
+ *pstart_addr = start_addr;
+}
+
+static uint32_t cirrus_get_bpp16_depth(CirrusVGAState * s)
+{
+ uint32_t ret = 16;
+
+ switch (s->cirrus_hidden_dac_data & 0xf) {
+ case 0:
+ ret = 15;
+ break; /* Sierra HiColor */
+ case 1:
+ ret = 16;
+ break; /* XGA HiColor */
+ default:
+#ifdef DEBUG_CIRRUS
+ printf("cirrus: invalid DAC value %x in 16bpp\n",
+ (s->cirrus_hidden_dac_data & 0xf));
+#endif
+ ret = 15; /* XXX */
+ break;
+ }
+ return ret;
+}
+
+static int cirrus_get_bpp(VGAState *s1)
+{
+ CirrusVGAState * s = (CirrusVGAState *)s1;
+ uint32_t ret = 8;
+
+ if ((s->sr[0x07] & 0x01) != 0) {
+ /* Cirrus SVGA */
+ switch (s->sr[0x07] & CIRRUS_SR7_BPP_MASK) {
+ case CIRRUS_SR7_BPP_8:
+ ret = 8;
+ break;
+ case CIRRUS_SR7_BPP_16_DOUBLEVCLK:
+ ret = cirrus_get_bpp16_depth(s);
+ break;
+ case CIRRUS_SR7_BPP_24:
+ ret = 24;
+ break;
+ case CIRRUS_SR7_BPP_16:
+ ret = cirrus_get_bpp16_depth(s);
+ break;
+ case CIRRUS_SR7_BPP_32:
+ ret = 32;
+ break;
+ default:
+#ifdef DEBUG_CIRRUS
+ printf("cirrus: unknown bpp - sr7=%x\n", s->sr[0x7]);
+#endif
+ ret = 8;
+ break;
+ }
+ } else {
+ /* VGA */
+ ret = 0;
+ }
+
+ return ret;
+}
+
+static void cirrus_get_resolution(VGAState *s, int *pwidth, int *pheight)
+{
+ int width, height;
+
+ width = (s->cr[0x01] + 1) * 8;
+ height = s->cr[0x12] |
+ ((s->cr[0x07] & 0x02) << 7) |
+ ((s->cr[0x07] & 0x40) << 3);
+ height = (height + 1);
+ /* interlace support */
+ if (s->cr[0x1a] & 0x01)
+ height = height * 2;
+ *pwidth = width;
+ *pheight = height;
+}
+
+/***************************************
+ *
+ * bank memory
+ *
+ ***************************************/
+
+static void cirrus_update_bank_ptr(CirrusVGAState * s, unsigned bank_index)
+{
+ unsigned offset;
+ unsigned limit;
+
+ if ((s->gr[0x0b] & 0x01) != 0) /* dual bank */
+ offset = s->gr[0x09 + bank_index];
+ else /* single bank */
+ offset = s->gr[0x09];
+
+ if ((s->gr[0x0b] & 0x20) != 0)
+ offset <<= 14;
+ else
+ offset <<= 12;
+
+ if (s->vram_size <= offset)
+ limit = 0;
+ else
+ limit = s->vram_size - offset;
+
+ if (((s->gr[0x0b] & 0x01) == 0) && (bank_index != 0)) {
+ if (limit > 0x8000) {
+ offset += 0x8000;
+ limit -= 0x8000;
+ } else {
+ limit = 0;
+ }
+ }
+
+ if (limit > 0) {
+ s->cirrus_bank_base[bank_index] = offset;
+ s->cirrus_bank_limit[bank_index] = limit;
+ } else {
+ s->cirrus_bank_base[bank_index] = 0;
+ s->cirrus_bank_limit[bank_index] = 0;
+ }
+}
+
+/***************************************
+ *
+ * I/O access between 0x3c4-0x3c5
+ *
+ ***************************************/
+
+static int
+cirrus_hook_read_sr(CirrusVGAState * s, unsigned reg_index, int *reg_value)
+{
+ switch (reg_index) {
+ case 0x00: // Standard VGA
+ case 0x01: // Standard VGA
+ case 0x02: // Standard VGA
+ case 0x03: // Standard VGA
+ case 0x04: // Standard VGA
+ return CIRRUS_HOOK_NOT_HANDLED;
+ case 0x06: // Unlock Cirrus extensions
+ *reg_value = s->sr[reg_index];
+ break;
+ case 0x10:
+ case 0x30:
+ case 0x50:
+ case 0x70: // Graphics Cursor X
+ case 0x90:
+ case 0xb0:
+ case 0xd0:
+ case 0xf0: // Graphics Cursor X
+ *reg_value = s->sr[0x10];
+ break;
+ case 0x11:
+ case 0x31:
+ case 0x51:
+ case 0x71: // Graphics Cursor Y
+ case 0x91:
+ case 0xb1:
+ case 0xd1:
+ case 0xf1: // Graphics Cursor Y
+ *reg_value = s->sr[0x11];
+ break;
+ case 0x05: // ???
+ case 0x07: // Extended Sequencer Mode
+ case 0x08: // EEPROM Control
+ case 0x09: // Scratch Register 0
+ case 0x0a: // Scratch Register 1
+ case 0x0b: // VCLK 0
+ case 0x0c: // VCLK 1
+ case 0x0d: // VCLK 2
+ case 0x0e: // VCLK 3
+ case 0x0f: // DRAM Control
+ case 0x12: // Graphics Cursor Attribute
+ case 0x13: // Graphics Cursor Pattern Address
+ case 0x14: // Scratch Register 2
+ case 0x15: // Scratch Register 3
+ case 0x16: // Performance Tuning Register
+ case 0x17: // Configuration Readback and Extended Control
+ case 0x18: // Signature Generator Control
+ case 0x19: // Signal Generator Result
+ case 0x1a: // Signal Generator Result
+ case 0x1b: // VCLK 0 Denominator & Post
+ case 0x1c: // VCLK 1 Denominator & Post
+ case 0x1d: // VCLK 2 Denominator & Post
+ case 0x1e: // VCLK 3 Denominator & Post
+ case 0x1f: // BIOS Write Enable and MCLK select
+#ifdef DEBUG_CIRRUS
+ printf("cirrus: handled inport sr_index %02x\n", reg_index);
+#endif
+ *reg_value = s->sr[reg_index];
+ break;
+ default:
+#ifdef DEBUG_CIRRUS
+ printf("cirrus: inport sr_index %02x\n", reg_index);
+#endif
+ *reg_value = 0xff;
+ break;
+ }
+
+ return CIRRUS_HOOK_HANDLED;
+}
+
+static int
+cirrus_hook_write_sr(CirrusVGAState * s, unsigned reg_index, int reg_value)
+{
+ switch (reg_index) {
+ case 0x00: // Standard VGA
+ case 0x01: // Standard VGA
+ case 0x02: // Standard VGA
+ case 0x03: // Standard VGA
+ case 0x04: // Standard VGA
+ return CIRRUS_HOOK_NOT_HANDLED;
+ case 0x06: // Unlock Cirrus extensions
+ reg_value &= 0x17;
+ if (reg_value == 0x12) {
+ s->sr[reg_index] = 0x12;
+ } else {
+ s->sr[reg_index] = 0x0f;
+ }
+ break;
+ case 0x10:
+ case 0x30:
+ case 0x50:
+ case 0x70: // Graphics Cursor X
+ case 0x90:
+ case 0xb0:
+ case 0xd0:
+ case 0xf0: // Graphics Cursor X
+ s->sr[0x10] = reg_value;
+ s->hw_cursor_x = (reg_value << 3) | (reg_index >> 5);
+ break;
+ case 0x11:
+ case 0x31:
+ case 0x51:
+ case 0x71: // Graphics Cursor Y
+ case 0x91:
+ case 0xb1:
+ case 0xd1:
+ case 0xf1: // Graphics Cursor Y
+ s->sr[0x11] = reg_value;
+ s->hw_cursor_y = (reg_value << 3) | (reg_index >> 5);
+ break;
+ case 0x07: // Extended Sequencer Mode
+ case 0x08: // EEPROM Control
+ case 0x09: // Scratch Register 0
+ case 0x0a: // Scratch Register 1
+ case 0x0b: // VCLK 0
+ case 0x0c: // VCLK 1
+ case 0x0d: // VCLK 2
+ case 0x0e: // VCLK 3
+ case 0x0f: // DRAM Control
+ case 0x12: // Graphics Cursor Attribute
+ case 0x13: // Graphics Cursor Pattern Address
+ case 0x14: // Scratch Register 2
+ case 0x15: // Scratch Register 3
+ case 0x16: // Performance Tuning Register
+ case 0x18: // Signature Generator Control
+ case 0x19: // Signature Generator Result
+ case 0x1a: // Signature Generator Result
+ case 0x1b: // VCLK 0 Denominator & Post
+ case 0x1c: // VCLK 1 Denominator & Post
+ case 0x1d: // VCLK 2 Denominator & Post
+ case 0x1e: // VCLK 3 Denominator & Post
+ case 0x1f: // BIOS Write Enable and MCLK select
+ s->sr[reg_index] = reg_value;
+#ifdef DEBUG_CIRRUS
+ printf("cirrus: handled outport sr_index %02x, sr_value %02x\n",
+ reg_index, reg_value);
+#endif
+ break;
+ case 0x17: // Configuration Readback and Extended Control
+ s->sr[reg_index] = reg_value;
+ cirrus_update_memory_access(s);
+ break;
+ default:
+#ifdef DEBUG_CIRRUS
+ printf("cirrus: outport sr_index %02x, sr_value %02x\n", reg_index,
+ reg_value);
+#endif
+ break;
+ }
+
+ return CIRRUS_HOOK_HANDLED;
+}
+
+/***************************************
+ *
+ * I/O access at 0x3c6
+ *
+ ***************************************/
+
+static void cirrus_read_hidden_dac(CirrusVGAState * s, int *reg_value)
+{
+ *reg_value = 0xff;
+ if (++s->cirrus_hidden_dac_lockindex == 5) {
+ *reg_value = s->cirrus_hidden_dac_data;
+ s->cirrus_hidden_dac_lockindex = 0;
+ }
+}
+
+static void cirrus_write_hidden_dac(CirrusVGAState * s, int reg_value)
+{
+ if (s->cirrus_hidden_dac_lockindex == 4) {
+ s->cirrus_hidden_dac_data = reg_value;
+#if defined(DEBUG_CIRRUS)
+ printf("cirrus: outport hidden DAC, value %02x\n", reg_value);
+#endif
+ }
+ s->cirrus_hidden_dac_lockindex = 0;
+}
+
+/***************************************
+ *
+ * I/O access at 0x3c9
+ *
+ ***************************************/
+
+static int cirrus_hook_read_palette(CirrusVGAState * s, int *reg_value)
+{
+ if (!(s->sr[0x12] & CIRRUS_CURSOR_HIDDENPEL))
+ return CIRRUS_HOOK_NOT_HANDLED;
+ *reg_value =
+ s->cirrus_hidden_palette[(s->dac_read_index & 0x0f) * 3 +
+ s->dac_sub_index];
+ if (++s->dac_sub_index == 3) {
+ s->dac_sub_index = 0;
+ s->dac_read_index++;
+ }
+ return CIRRUS_HOOK_HANDLED;
+}
+
+static int cirrus_hook_write_palette(CirrusVGAState * s, int reg_value)
+{
+ if (!(s->sr[0x12] & CIRRUS_CURSOR_HIDDENPEL))
+ return CIRRUS_HOOK_NOT_HANDLED;
+ s->dac_cache[s->dac_sub_index] = reg_value;
+ if (++s->dac_sub_index == 3) {
+ memcpy(&s->cirrus_hidden_palette[(s->dac_write_index & 0x0f) * 3],
+ s->dac_cache, 3);
+ /* XXX update cursor */
+ s->dac_sub_index = 0;
+ s->dac_write_index++;
+ }
+ return CIRRUS_HOOK_HANDLED;
+}
+
+/***************************************
+ *
+ * I/O access between 0x3ce-0x3cf
+ *
+ ***************************************/
+
+static int
+cirrus_hook_read_gr(CirrusVGAState * s, unsigned reg_index, int *reg_value)
+{
+ switch (reg_index) {
+ case 0x00: // Standard VGA, BGCOLOR 0x000000ff
+ *reg_value = s->cirrus_shadow_gr0;
+ return CIRRUS_HOOK_HANDLED;
+ case 0x01: // Standard VGA, FGCOLOR 0x000000ff
+ *reg_value = s->cirrus_shadow_gr1;
+ return CIRRUS_HOOK_HANDLED;
+ case 0x02: // Standard VGA
+ case 0x03: // Standard VGA
+ case 0x04: // Standard VGA
+ case 0x06: // Standard VGA
+ case 0x07: // Standard VGA
+ case 0x08: // Standard VGA
+ return CIRRUS_HOOK_NOT_HANDLED;
+ case 0x05: // Standard VGA, Cirrus extended mode
+ default:
+ break;
+ }
+
+ if (reg_index < 0x3a) {
+ *reg_value = s->gr[reg_index];
+ } else {
+#ifdef DEBUG_CIRRUS
+ printf("cirrus: inport gr_index %02x\n", reg_index);
+#endif
+ *reg_value = 0xff;
+ }
+
+ return CIRRUS_HOOK_HANDLED;
+}
+
+static int
+cirrus_hook_write_gr(CirrusVGAState * s, unsigned reg_index, int reg_value)
+{
+#if defined(DEBUG_BITBLT) && 0
+ printf("gr%02x: %02x\n", reg_index, reg_value);
+#endif
+ switch (reg_index) {
+ case 0x00: // Standard VGA, BGCOLOR 0x000000ff
+ s->cirrus_shadow_gr0 = reg_value;
+ return CIRRUS_HOOK_NOT_HANDLED;
+ case 0x01: // Standard VGA, FGCOLOR 0x000000ff
+ s->cirrus_shadow_gr1 = reg_value;
+ return CIRRUS_HOOK_NOT_HANDLED;
+ case 0x02: // Standard VGA
+ case 0x03: // Standard VGA
+ case 0x04: // Standard VGA
+ case 0x06: // Standard VGA
+ case 0x07: // Standard VGA
+ case 0x08: // Standard VGA
+ return CIRRUS_HOOK_NOT_HANDLED;
+ case 0x05: // Standard VGA, Cirrus extended mode
+ s->gr[reg_index] = reg_value & 0x7f;
+ cirrus_update_memory_access(s);
+ break;
+ case 0x09: // bank offset #0
+ case 0x0A: // bank offset #1
+ s->gr[reg_index] = reg_value;
+ cirrus_update_bank_ptr(s, 0);
+ cirrus_update_bank_ptr(s, 1);
+ break;
+ case 0x0B:
+ s->gr[reg_index] = reg_value;
+ cirrus_update_bank_ptr(s, 0);
+ cirrus_update_bank_ptr(s, 1);
+ cirrus_update_memory_access(s);
+ break;
+ case 0x10: // BGCOLOR 0x0000ff00
+ case 0x11: // FGCOLOR 0x0000ff00
+ case 0x12: // BGCOLOR 0x00ff0000
+ case 0x13: // FGCOLOR 0x00ff0000
+ case 0x14: // BGCOLOR 0xff000000
+ case 0x15: // FGCOLOR 0xff000000
+ case 0x20: // BLT WIDTH 0x0000ff
+ case 0x22: // BLT HEIGHT 0x0000ff
+ case 0x24: // BLT DEST PITCH 0x0000ff
+ case 0x26: // BLT SRC PITCH 0x0000ff
+ case 0x28: // BLT DEST ADDR 0x0000ff
+ case 0x29: // BLT DEST ADDR 0x00ff00
+ case 0x2c: // BLT SRC ADDR 0x0000ff
+ case 0x2d: // BLT SRC ADDR 0x00ff00
+ case 0x2f: // BLT WRITEMASK
+ case 0x30: // BLT MODE
+ case 0x32: // RASTER OP
+ case 0x33: // BLT MODEEXT
+ case 0x34: // BLT TRANSPARENT COLOR 0x00ff
+ case 0x35: // BLT TRANSPARENT COLOR 0xff00
+ case 0x38: // BLT TRANSPARENT COLOR MASK 0x00ff
+ case 0x39: // BLT TRANSPARENT COLOR MASK 0xff00
+ s->gr[reg_index] = reg_value;
+ break;
+ case 0x21: // BLT WIDTH 0x001f00
+ case 0x23: // BLT HEIGHT 0x001f00
+ case 0x25: // BLT DEST PITCH 0x001f00
+ case 0x27: // BLT SRC PITCH 0x001f00
+ s->gr[reg_index] = reg_value & 0x1f;
+ break;
+ case 0x2a: // BLT DEST ADDR 0x3f0000
+ s->gr[reg_index] = reg_value & 0x3f;
+ /* if auto start mode, starts bit blt now */
+ if (s->gr[0x31] & CIRRUS_BLT_AUTOSTART) {
+ cirrus_bitblt_start(s);
+ }
+ break;
+ case 0x2e: // BLT SRC ADDR 0x3f0000
+ s->gr[reg_index] = reg_value & 0x3f;
+ break;
+ case 0x31: // BLT STATUS/START
+ cirrus_write_bitblt(s, reg_value);
+ break;
+ default:
+#ifdef DEBUG_CIRRUS
+ printf("cirrus: outport gr_index %02x, gr_value %02x\n", reg_index,
+ reg_value);
+#endif
+ break;
+ }
+
+ return CIRRUS_HOOK_HANDLED;
+}
+
+/***************************************
+ *
+ * I/O access between 0x3d4-0x3d5
+ *
+ ***************************************/
+
+static int
+cirrus_hook_read_cr(CirrusVGAState * s, unsigned reg_index, int *reg_value)
+{
+ switch (reg_index) {
+ case 0x00: // Standard VGA
+ case 0x01: // Standard VGA
+ case 0x02: // Standard VGA
+ case 0x03: // Standard VGA
+ case 0x04: // Standard VGA
+ case 0x05: // Standard VGA
+ case 0x06: // Standard VGA
+ case 0x07: // Standard VGA
+ case 0x08: // Standard VGA
+ case 0x09: // Standard VGA
+ case 0x0a: // Standard VGA
+ case 0x0b: // Standard VGA
+ case 0x0c: // Standard VGA
+ case 0x0d: // Standard VGA
+ case 0x0e: // Standard VGA
+ case 0x0f: // Standard VGA
+ case 0x10: // Standard VGA
+ case 0x11: // Standard VGA
+ case 0x12: // Standard VGA
+ case 0x13: // Standard VGA
+ case 0x14: // Standard VGA
+ case 0x15: // Standard VGA
+ case 0x16: // Standard VGA
+ case 0x17: // Standard VGA
+ case 0x18: // Standard VGA
+ return CIRRUS_HOOK_NOT_HANDLED;
+ case 0x19: // Interlace End
+ case 0x1a: // Miscellaneous Control
+ case 0x1b: // Extended Display Control
+ case 0x1c: // Sync Adjust and Genlock
+ case 0x1d: // Overlay Extended Control
+ case 0x22: // Graphics Data Latches Readback (R)
+ case 0x24: // Attribute Controller Toggle Readback (R)
+ case 0x25: // Part Status
+ case 0x27: // Part ID (R)
+ *reg_value = s->cr[reg_index];
+ break;
+ case 0x26: // Attribute Controller Index Readback (R)
+ *reg_value = s->ar_index & 0x3f;
+ break;
+ default:
+#ifdef DEBUG_CIRRUS
+ printf("cirrus: inport cr_index %02x\n", reg_index);
+ *reg_value = 0xff;
+#endif
+ break;
+ }
+
+ return CIRRUS_HOOK_HANDLED;
+}
+
+static int
+cirrus_hook_write_cr(CirrusVGAState * s, unsigned reg_index, int reg_value)
+{
+ switch (reg_index) {
+ case 0x00: // Standard VGA
+ case 0x01: // Standard VGA
+ case 0x02: // Standard VGA
+ case 0x03: // Standard VGA
+ case 0x04: // Standard VGA
+ case 0x05: // Standard VGA
+ case 0x06: // Standard VGA
+ case 0x07: // Standard VGA
+ case 0x08: // Standard VGA
+ case 0x09: // Standard VGA
+ case 0x0a: // Standard VGA
+ case 0x0b: // Standard VGA
+ case 0x0c: // Standard VGA
+ case 0x0d: // Standard VGA
+ case 0x0e: // Standard VGA
+ case 0x0f: // Standard VGA
+ case 0x10: // Standard VGA
+ case 0x11: // Standard VGA
+ case 0x12: // Standard VGA
+ case 0x13: // Standard VGA
+ case 0x14: // Standard VGA
+ case 0x15: // Standard VGA
+ case 0x16: // Standard VGA
+ case 0x17: // Standard VGA
+ case 0x18: // Standard VGA
+ return CIRRUS_HOOK_NOT_HANDLED;
+ case 0x19: // Interlace End
+ case 0x1a: // Miscellaneous Control
+ case 0x1b: // Extended Display Control
+ case 0x1c: // Sync Adjust and Genlock
+ case 0x1d: // Overlay Extended Control
+ s->cr[reg_index] = reg_value;
+#ifdef DEBUG_CIRRUS
+ printf("cirrus: handled outport cr_index %02x, cr_value %02x\n",
+ reg_index, reg_value);
+#endif
+ break;
+ case 0x22: // Graphics Data Latches Readback (R)
+ case 0x24: // Attribute Controller Toggle Readback (R)
+ case 0x26: // Attribute Controller Index Readback (R)
+ case 0x27: // Part ID (R)
+ break;
+ case 0x25: // Part Status
+ default:
+#ifdef DEBUG_CIRRUS
+ printf("cirrus: outport cr_index %02x, cr_value %02x\n", reg_index,
+ reg_value);
+#endif
+ break;
+ }
+
+ return CIRRUS_HOOK_HANDLED;
+}
+
+/***************************************
+ *
+ * memory-mapped I/O (bitblt)
+ *
+ ***************************************/
+
+static uint8_t cirrus_mmio_blt_read(CirrusVGAState * s, unsigned address)
+{
+ int value = 0xff;
+
+ switch (address) {
+ case (CIRRUS_MMIO_BLTBGCOLOR + 0):
+ cirrus_hook_read_gr(s, 0x00, &value);
+ break;
+ case (CIRRUS_MMIO_BLTBGCOLOR + 1):
+ cirrus_hook_read_gr(s, 0x10, &value);
+ break;
+ case (CIRRUS_MMIO_BLTBGCOLOR + 2):
+ cirrus_hook_read_gr(s, 0x12, &value);
+ break;
+ case (CIRRUS_MMIO_BLTBGCOLOR + 3):
+ cirrus_hook_read_gr(s, 0x14, &value);
+ break;
+ case (CIRRUS_MMIO_BLTFGCOLOR + 0):
+ cirrus_hook_read_gr(s, 0x01, &value);
+ break;
+ case (CIRRUS_MMIO_BLTFGCOLOR + 1):
+ cirrus_hook_read_gr(s, 0x11, &value);
+ break;
+ case (CIRRUS_MMIO_BLTFGCOLOR + 2):
+ cirrus_hook_read_gr(s, 0x13, &value);
+ break;
+ case (CIRRUS_MMIO_BLTFGCOLOR + 3):
+ cirrus_hook_read_gr(s, 0x15, &value);
+ break;
+ case (CIRRUS_MMIO_BLTWIDTH + 0):
+ cirrus_hook_read_gr(s, 0x20, &value);
+ break;
+ case (CIRRUS_MMIO_BLTWIDTH + 1):
+ cirrus_hook_read_gr(s, 0x21, &value);
+ break;
+ case (CIRRUS_MMIO_BLTHEIGHT + 0):
+ cirrus_hook_read_gr(s, 0x22, &value);
+ break;
+ case (CIRRUS_MMIO_BLTHEIGHT + 1):
+ cirrus_hook_read_gr(s, 0x23, &value);
+ break;
+ case (CIRRUS_MMIO_BLTDESTPITCH + 0):
+ cirrus_hook_read_gr(s, 0x24, &value);
+ break;
+ case (CIRRUS_MMIO_BLTDESTPITCH + 1):
+ cirrus_hook_read_gr(s, 0x25, &value);
+ break;
+ case (CIRRUS_MMIO_BLTSRCPITCH + 0):
+ cirrus_hook_read_gr(s, 0x26, &value);
+ break;
+ case (CIRRUS_MMIO_BLTSRCPITCH + 1):
+ cirrus_hook_read_gr(s, 0x27, &value);
+ break;
+ case (CIRRUS_MMIO_BLTDESTADDR + 0):
+ cirrus_hook_read_gr(s, 0x28, &value);
+ break;
+ case (CIRRUS_MMIO_BLTDESTADDR + 1):
+ cirrus_hook_read_gr(s, 0x29, &value);
+ break;
+ case (CIRRUS_MMIO_BLTDESTADDR + 2):
+ cirrus_hook_read_gr(s, 0x2a, &value);
+ break;
+ case (CIRRUS_MMIO_BLTSRCADDR + 0):
+ cirrus_hook_read_gr(s, 0x2c, &value);
+ break;
+ case (CIRRUS_MMIO_BLTSRCADDR + 1):
+ cirrus_hook_read_gr(s, 0x2d, &value);
+ break;
+ case (CIRRUS_MMIO_BLTSRCADDR + 2):
+ cirrus_hook_read_gr(s, 0x2e, &value);
+ break;
+ case CIRRUS_MMIO_BLTWRITEMASK:
+ cirrus_hook_read_gr(s, 0x2f, &value);
+ break;
+ case CIRRUS_MMIO_BLTMODE:
+ cirrus_hook_read_gr(s, 0x30, &value);
+ break;
+ case CIRRUS_MMIO_BLTROP:
+ cirrus_hook_read_gr(s, 0x32, &value);
+ break;
+ case CIRRUS_MMIO_BLTMODEEXT:
+ cirrus_hook_read_gr(s, 0x33, &value);
+ break;
+ case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 0):
+ cirrus_hook_read_gr(s, 0x34, &value);
+ break;
+ case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 1):
+ cirrus_hook_read_gr(s, 0x35, &value);
+ break;
+ case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 0):
+ cirrus_hook_read_gr(s, 0x38, &value);
+ break;
+ case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 1):
+ cirrus_hook_read_gr(s, 0x39, &value);
+ break;
+ case CIRRUS_MMIO_BLTSTATUS:
+ cirrus_hook_read_gr(s, 0x31, &value);
+ break;
+ default:
+#ifdef DEBUG_CIRRUS
+ printf("cirrus: mmio read - address 0x%04x\n", address);
+#endif
+ break;
+ }
+
+ return (uint8_t) value;
+}
+
+static void cirrus_mmio_blt_write(CirrusVGAState * s, unsigned address,
+ uint8_t value)
+{
+ switch (address) {
+ case (CIRRUS_MMIO_BLTBGCOLOR + 0):
+ cirrus_hook_write_gr(s, 0x00, value);
+ break;
+ case (CIRRUS_MMIO_BLTBGCOLOR + 1):
+ cirrus_hook_write_gr(s, 0x10, value);
+ break;
+ case (CIRRUS_MMIO_BLTBGCOLOR + 2):
+ cirrus_hook_write_gr(s, 0x12, value);
+ break;
+ case (CIRRUS_MMIO_BLTBGCOLOR + 3):
+ cirrus_hook_write_gr(s, 0x14, value);
+ break;
+ case (CIRRUS_MMIO_BLTFGCOLOR + 0):
+ cirrus_hook_write_gr(s, 0x01, value);
+ break;
+ case (CIRRUS_MMIO_BLTFGCOLOR + 1):
+ cirrus_hook_write_gr(s, 0x11, value);
+ break;
+ case (CIRRUS_MMIO_BLTFGCOLOR + 2):
+ cirrus_hook_write_gr(s, 0x13, value);
+ break;
+ case (CIRRUS_MMIO_BLTFGCOLOR + 3):
+ cirrus_hook_write_gr(s, 0x15, value);
+ break;
+ case (CIRRUS_MMIO_BLTWIDTH + 0):
+ cirrus_hook_write_gr(s, 0x20, value);
+ break;
+ case (CIRRUS_MMIO_BLTWIDTH + 1):
+ cirrus_hook_write_gr(s, 0x21, value);
+ break;
+ case (CIRRUS_MMIO_BLTHEIGHT + 0):
+ cirrus_hook_write_gr(s, 0x22, value);
+ break;
+ case (CIRRUS_MMIO_BLTHEIGHT + 1):
+ cirrus_hook_write_gr(s, 0x23, value);
+ break;
+ case (CIRRUS_MMIO_BLTDESTPITCH + 0):
+ cirrus_hook_write_gr(s, 0x24, value);
+ break;
+ case (CIRRUS_MMIO_BLTDESTPITCH + 1):
+ cirrus_hook_write_gr(s, 0x25, value);
+ break;
+ case (CIRRUS_MMIO_BLTSRCPITCH + 0):
+ cirrus_hook_write_gr(s, 0x26, value);
+ break;
+ case (CIRRUS_MMIO_BLTSRCPITCH + 1):
+ cirrus_hook_write_gr(s, 0x27, value);
+ break;
+ case (CIRRUS_MMIO_BLTDESTADDR + 0):
+ cirrus_hook_write_gr(s, 0x28, value);
+ break;
+ case (CIRRUS_MMIO_BLTDESTADDR + 1):
+ cirrus_hook_write_gr(s, 0x29, value);
+ break;
+ case (CIRRUS_MMIO_BLTDESTADDR + 2):
+ cirrus_hook_write_gr(s, 0x2a, value);
+ break;
+ case (CIRRUS_MMIO_BLTDESTADDR + 3):
+ /* ignored */
+ break;
+ case (CIRRUS_MMIO_BLTSRCADDR + 0):
+ cirrus_hook_write_gr(s, 0x2c, value);
+ break;
+ case (CIRRUS_MMIO_BLTSRCADDR + 1):
+ cirrus_hook_write_gr(s, 0x2d, value);
+ break;
+ case (CIRRUS_MMIO_BLTSRCADDR + 2):
+ cirrus_hook_write_gr(s, 0x2e, value);
+ break;
+ case CIRRUS_MMIO_BLTWRITEMASK:
+ cirrus_hook_write_gr(s, 0x2f, value);
+ break;
+ case CIRRUS_MMIO_BLTMODE:
+ cirrus_hook_write_gr(s, 0x30, value);
+ break;
+ case CIRRUS_MMIO_BLTROP:
+ cirrus_hook_write_gr(s, 0x32, value);
+ break;
+ case CIRRUS_MMIO_BLTMODEEXT:
+ cirrus_hook_write_gr(s, 0x33, value);
+ break;
+ case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 0):
+ cirrus_hook_write_gr(s, 0x34, value);
+ break;
+ case (CIRRUS_MMIO_BLTTRANSPARENTCOLOR + 1):
+ cirrus_hook_write_gr(s, 0x35, value);
+ break;
+ case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 0):
+ cirrus_hook_write_gr(s, 0x38, value);
+ break;
+ case (CIRRUS_MMIO_BLTTRANSPARENTCOLORMASK + 1):
+ cirrus_hook_write_gr(s, 0x39, value);
+ break;
+ case CIRRUS_MMIO_BLTSTATUS:
+ cirrus_hook_write_gr(s, 0x31, value);
+ break;
+ default:
+#ifdef DEBUG_CIRRUS
+ printf("cirrus: mmio write - addr 0x%04x val 0x%02x (ignored)\n",
+ address, value);
+#endif
+ break;
+ }
+}
+
+/***************************************
+ *
+ * write mode 4/5
+ *
+ * assume TARGET_PAGE_SIZE >= 16
+ *
+ ***************************************/
+
+static void cirrus_mem_writeb_mode4and5_8bpp(CirrusVGAState * s,
+ unsigned mode,
+ unsigned offset,
+ uint32_t mem_value)
+{
+ int x;
+ unsigned val = mem_value;
+ uint8_t *dst;
+
+ dst = s->vram_ptr + offset;
+ for (x = 0; x < 8; x++) {
+ if (val & 0x80) {
+ *dst++ = s->cirrus_shadow_gr1;
+ } else if (mode == 5) {
+ *dst++ = s->cirrus_shadow_gr0;
+ }
+ val <<= 1;
+ }
+ cpu_physical_memory_set_dirty(s->vram_offset + offset);
+ cpu_physical_memory_set_dirty(s->vram_offset + offset + 7);
+}
+
+static void cirrus_mem_writeb_mode4and5_16bpp(CirrusVGAState * s,
+ unsigned mode,
+ unsigned offset,
+ uint32_t mem_value)
+{
+ int x;
+ unsigned val = mem_value;
+ uint8_t *dst;
+
+ dst = s->vram_ptr + offset;
+ for (x = 0; x < 8; x++) {
+ if (val & 0x80) {
+ *dst++ = s->cirrus_shadow_gr1;
+ *dst++ = s->gr[0x11];
+ } else if (mode == 5) {
+ *dst++ = s->cirrus_shadow_gr0;
+ *dst++ = s->gr[0x10];
+ }
+ val <<= 1;
+ }
+ cpu_physical_memory_set_dirty(s->vram_offset + offset);
+ cpu_physical_memory_set_dirty(s->vram_offset + offset + 15);
+}
+
+/***************************************
+ *
+ * memory access between 0xa0000-0xbffff
+ *
+ ***************************************/
+
+static uint32_t cirrus_vga_mem_readb(void *opaque, target_phys_addr_t addr)
+{
+ CirrusVGAState *s = opaque;
+ unsigned bank_index;
+ unsigned bank_offset;
+ uint32_t val;
+
+ if ((s->sr[0x07] & 0x01) == 0) {
+ return vga_mem_readb(s, addr);
+ }
+
+ addr &= 0x1ffff;
+
+ if (addr < 0x10000) {
+ /* XXX handle bitblt */
+ /* video memory */
+ bank_index = addr >> 15;
+ bank_offset = addr & 0x7fff;
+ if (bank_offset < s->cirrus_bank_limit[bank_index]) {
+ bank_offset += s->cirrus_bank_base[bank_index];
+ if ((s->gr[0x0B] & 0x14) == 0x14) {
+ bank_offset <<= 4;
+ } else if (s->gr[0x0B] & 0x02) {
+ bank_offset <<= 3;
+ }
+ bank_offset &= s->cirrus_addr_mask;
+ val = *(s->vram_ptr + bank_offset);
+ } else
+ val = 0xff;
+ } else if (addr >= 0x18000 && addr < 0x18100) {
+ /* memory-mapped I/O */
+ val = 0xff;
+ if ((s->sr[0x17] & 0x44) == 0x04) {
+ val = cirrus_mmio_blt_read(s, addr & 0xff);
+ }
+ } else {
+ val = 0xff;
+#ifdef DEBUG_CIRRUS
+ printf("cirrus: mem_readb %06x\n", addr);
+#endif
+ }
+ return val;
+}
+
+static uint32_t cirrus_vga_mem_readw(void *opaque, target_phys_addr_t addr)
+{
+ uint32_t v;
+#ifdef TARGET_WORDS_BIGENDIAN
+ v = cirrus_vga_mem_readb(opaque, addr) << 8;
+ v |= cirrus_vga_mem_readb(opaque, addr + 1);
+#else
+ v = cirrus_vga_mem_readb(opaque, addr);
+ v |= cirrus_vga_mem_readb(opaque, addr + 1) << 8;
+#endif
+ return v;
+}
+
+static uint32_t cirrus_vga_mem_readl(void *opaque, target_phys_addr_t addr)
+{
+ uint32_t v;
+#ifdef TARGET_WORDS_BIGENDIAN
+ v = cirrus_vga_mem_readb(opaque, addr) << 24;
+ v |= cirrus_vga_mem_readb(opaque, addr + 1) << 16;
+ v |= cirrus_vga_mem_readb(opaque, addr + 2) << 8;
+ v |= cirrus_vga_mem_readb(opaque, addr + 3);
+#else
+ v = cirrus_vga_mem_readb(opaque, addr);
+ v |= cirrus_vga_mem_readb(opaque, addr + 1) << 8;
+ v |= cirrus_vga_mem_readb(opaque, addr + 2) << 16;
+ v |= cirrus_vga_mem_readb(opaque, addr + 3) << 24;
+#endif
+ return v;
+}
+
+static void cirrus_vga_mem_writeb(void *opaque, target_phys_addr_t addr,
+ uint32_t mem_value)
+{
+ CirrusVGAState *s = opaque;
+ unsigned bank_index;
+ unsigned bank_offset;
+ unsigned mode;
+
+ if ((s->sr[0x07] & 0x01) == 0) {
+ vga_mem_writeb(s, addr, mem_value);
+ return;
+ }
+
+ addr &= 0x1ffff;
+
+ if (addr < 0x10000) {
+ if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
+ /* bitblt */
+ *s->cirrus_srcptr++ = (uint8_t) mem_value;
+ if (s->cirrus_srcptr >= s->cirrus_srcptr_end) {
+ cirrus_bitblt_cputovideo_next(s);
+ }
+ } else {
+ /* video memory */
+ bank_index = addr >> 15;
+ bank_offset = addr & 0x7fff;
+ if (bank_offset < s->cirrus_bank_limit[bank_index]) {
+ bank_offset += s->cirrus_bank_base[bank_index];
+ if ((s->gr[0x0B] & 0x14) == 0x14) {
+ bank_offset <<= 4;
+ } else if (s->gr[0x0B] & 0x02) {
+ bank_offset <<= 3;
+ }
+ bank_offset &= s->cirrus_addr_mask;
+ mode = s->gr[0x05] & 0x7;
+ if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) {
+ *(s->vram_ptr + bank_offset) = mem_value;
+ cpu_physical_memory_set_dirty(s->vram_offset +
+ bank_offset);
+ } else {
+ if ((s->gr[0x0B] & 0x14) != 0x14) {
+ cirrus_mem_writeb_mode4and5_8bpp(s, mode,
+ bank_offset,
+ mem_value);
+ } else {
+ cirrus_mem_writeb_mode4and5_16bpp(s, mode,
+ bank_offset,
+ mem_value);
+ }
+ }
+ }
+ }
+ } else if (addr >= 0x18000 && addr < 0x18100) {
+ /* memory-mapped I/O */
+ if ((s->sr[0x17] & 0x44) == 0x04) {
+ cirrus_mmio_blt_write(s, addr & 0xff, mem_value);
+ }
+ } else {
+#ifdef DEBUG_CIRRUS
+ printf("cirrus: mem_writeb %06x value %02x\n", addr, mem_value);
+#endif
+ }
+}
+
+static void cirrus_vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+#ifdef TARGET_WORDS_BIGENDIAN
+ cirrus_vga_mem_writeb(opaque, addr, (val >> 8) & 0xff);
+ cirrus_vga_mem_writeb(opaque, addr + 1, val & 0xff);
+#else
+ cirrus_vga_mem_writeb(opaque, addr, val & 0xff);
+ cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
+#endif
+}
+
+static void cirrus_vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+#ifdef TARGET_WORDS_BIGENDIAN
+ cirrus_vga_mem_writeb(opaque, addr, (val >> 24) & 0xff);
+ cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff);
+ cirrus_vga_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff);
+ cirrus_vga_mem_writeb(opaque, addr + 3, val & 0xff);
+#else
+ cirrus_vga_mem_writeb(opaque, addr, val & 0xff);
+ cirrus_vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
+ cirrus_vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
+ cirrus_vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
+#endif
+}
+
+static CPUReadMemoryFunc *cirrus_vga_mem_read[3] = {
+ cirrus_vga_mem_readb,
+ cirrus_vga_mem_readw,
+ cirrus_vga_mem_readl,
+};
+
+static CPUWriteMemoryFunc *cirrus_vga_mem_write[3] = {
+ cirrus_vga_mem_writeb,
+ cirrus_vga_mem_writew,
+ cirrus_vga_mem_writel,
+};
+
+/***************************************
+ *
+ * hardware cursor
+ *
+ ***************************************/
+
+static inline void invalidate_cursor1(CirrusVGAState *s)
+{
+ if (s->last_hw_cursor_size) {
+ vga_invalidate_scanlines((VGAState *)s,
+ s->last_hw_cursor_y + s->last_hw_cursor_y_start,
+ s->last_hw_cursor_y + s->last_hw_cursor_y_end);
+ }
+}
+
+static inline void cirrus_cursor_compute_yrange(CirrusVGAState *s)
+{
+ const uint8_t *src;
+ uint32_t content;
+ int y, y_min, y_max;
+
+ src = s->vram_ptr + s->real_vram_size - 16 * 1024;
+ if (s->sr[0x12] & CIRRUS_CURSOR_LARGE) {
+ src += (s->sr[0x13] & 0x3c) * 256;
+ y_min = 64;
+ y_max = -1;
+ for(y = 0; y < 64; y++) {
+ content = ((uint32_t *)src)[0] |
+ ((uint32_t *)src)[1] |
+ ((uint32_t *)src)[2] |
+ ((uint32_t *)src)[3];
+ if (content) {
+ if (y < y_min)
+ y_min = y;
+ if (y > y_max)
+ y_max = y;
+ }
+ src += 16;
+ }
+ } else {
+ src += (s->sr[0x13] & 0x3f) * 256;
+ y_min = 32;
+ y_max = -1;
+ for(y = 0; y < 32; y++) {
+ content = ((uint32_t *)src)[0] |
+ ((uint32_t *)(src + 128))[0];
+ if (content) {
+ if (y < y_min)
+ y_min = y;
+ if (y > y_max)
+ y_max = y;
+ }
+ src += 4;
+ }
+ }
+ if (y_min > y_max) {
+ s->last_hw_cursor_y_start = 0;
+ s->last_hw_cursor_y_end = 0;
+ } else {
+ s->last_hw_cursor_y_start = y_min;
+ s->last_hw_cursor_y_end = y_max + 1;
+ }
+}
+
+/* NOTE: we do not currently handle the cursor bitmap change, so we
+ update the cursor only if it moves. */
+static void cirrus_cursor_invalidate(VGAState *s1)
+{
+ CirrusVGAState *s = (CirrusVGAState *)s1;
+ int size;
+
+ if (!s->sr[0x12] & CIRRUS_CURSOR_SHOW) {
+ size = 0;
+ } else {
+ if (s->sr[0x12] & CIRRUS_CURSOR_LARGE)
+ size = 64;
+ else
+ size = 32;
+ }
+ /* invalidate last cursor and new cursor if any change */
+ if (s->last_hw_cursor_size != size ||
+ s->last_hw_cursor_x != s->hw_cursor_x ||
+ s->last_hw_cursor_y != s->hw_cursor_y) {
+
+ invalidate_cursor1(s);
+
+ s->last_hw_cursor_size = size;
+ s->last_hw_cursor_x = s->hw_cursor_x;
+ s->last_hw_cursor_y = s->hw_cursor_y;
+ /* compute the real cursor min and max y */
+ cirrus_cursor_compute_yrange(s);
+ invalidate_cursor1(s);
+ }
+}
+
+static void cirrus_cursor_draw_line(VGAState *s1, uint8_t *d1, int scr_y)
+{
+ CirrusVGAState *s = (CirrusVGAState *)s1;
+ int w, h, bpp, x1, x2, poffset;
+ unsigned int color0, color1;
+ const uint8_t *palette, *src;
+ uint32_t content;
+
+ if (!(s->sr[0x12] & CIRRUS_CURSOR_SHOW))
+ return;
+ /* fast test to see if the cursor intersects with the scan line */
+ if (s->sr[0x12] & CIRRUS_CURSOR_LARGE) {
+ h = 64;
+ } else {
+ h = 32;
+ }
+ if (scr_y < s->hw_cursor_y ||
+ scr_y >= (s->hw_cursor_y + h))
+ return;
+
+ src = s->vram_ptr + s->real_vram_size - 16 * 1024;
+ if (s->sr[0x12] & CIRRUS_CURSOR_LARGE) {
+ src += (s->sr[0x13] & 0x3c) * 256;
+ src += (scr_y - s->hw_cursor_y) * 16;
+ poffset = 8;
+ content = ((uint32_t *)src)[0] |
+ ((uint32_t *)src)[1] |
+ ((uint32_t *)src)[2] |
+ ((uint32_t *)src)[3];
+ } else {
+ src += (s->sr[0x13] & 0x3f) * 256;
+ src += (scr_y - s->hw_cursor_y) * 4;
+ poffset = 128;
+ content = ((uint32_t *)src)[0] |
+ ((uint32_t *)(src + 128))[0];
+ }
+ /* if nothing to draw, no need to continue */
+ if (!content)
+ return;
+ w = h;
+
+ x1 = s->hw_cursor_x;
+ if (x1 >= s->last_scr_width)
+ return;
+ x2 = s->hw_cursor_x + w;
+ if (x2 > s->last_scr_width)
+ x2 = s->last_scr_width;
+ w = x2 - x1;
+ palette = s->cirrus_hidden_palette;
+ color0 = s->rgb_to_pixel(c6_to_8(palette[0x0 * 3]),
+ c6_to_8(palette[0x0 * 3 + 1]),
+ c6_to_8(palette[0x0 * 3 + 2]));
+ color1 = s->rgb_to_pixel(c6_to_8(palette[0xf * 3]),
+ c6_to_8(palette[0xf * 3 + 1]),
+ c6_to_8(palette[0xf * 3 + 2]));
+ bpp = ((s->ds->depth + 7) >> 3);
+ d1 += x1 * bpp;
+ switch(s->ds->depth) {
+ default:
+ break;
+ case 8:
+ vga_draw_cursor_line_8(d1, src, poffset, w, color0, color1, 0xff);
+ break;
+ case 15:
+ vga_draw_cursor_line_16(d1, src, poffset, w, color0, color1, 0x7fff);
+ break;
+ case 16:
+ vga_draw_cursor_line_16(d1, src, poffset, w, color0, color1, 0xffff);
+ break;
+ case 32:
+ vga_draw_cursor_line_32(d1, src, poffset, w, color0, color1, 0xffffff);
+ break;
+ }
+}
+
+/***************************************
+ *
+ * LFB memory access
+ *
+ ***************************************/
+
+static uint32_t cirrus_linear_readb(void *opaque, target_phys_addr_t addr)
+{
+ CirrusVGAState *s = (CirrusVGAState *) opaque;
+ uint32_t ret;
+
+ addr &= s->cirrus_addr_mask;
+
+ if (((s->sr[0x17] & 0x44) == 0x44) &&
+ ((addr & s->linear_mmio_mask) == s->linear_mmio_mask)) {
+ /* memory-mapped I/O */
+ ret = cirrus_mmio_blt_read(s, addr & 0xff);
+ } else if (0) {
+ /* XXX handle bitblt */
+ ret = 0xff;
+ } else {
+ /* video memory */
+ if ((s->gr[0x0B] & 0x14) == 0x14) {
+ addr <<= 4;
+ } else if (s->gr[0x0B] & 0x02) {
+ addr <<= 3;
+ }
+ addr &= s->cirrus_addr_mask;
+ ret = *(s->vram_ptr + addr);
+ }
+
+ return ret;
+}
+
+static uint32_t cirrus_linear_readw(void *opaque, target_phys_addr_t addr)
+{
+ uint32_t v;
+#ifdef TARGET_WORDS_BIGENDIAN
+ v = cirrus_linear_readb(opaque, addr) << 8;
+ v |= cirrus_linear_readb(opaque, addr + 1);
+#else
+ v = cirrus_linear_readb(opaque, addr);
+ v |= cirrus_linear_readb(opaque, addr + 1) << 8;
+#endif
+ return v;
+}
+
+static uint32_t cirrus_linear_readl(void *opaque, target_phys_addr_t addr)
+{
+ uint32_t v;
+#ifdef TARGET_WORDS_BIGENDIAN
+ v = cirrus_linear_readb(opaque, addr) << 24;
+ v |= cirrus_linear_readb(opaque, addr + 1) << 16;
+ v |= cirrus_linear_readb(opaque, addr + 2) << 8;
+ v |= cirrus_linear_readb(opaque, addr + 3);
+#else
+ v = cirrus_linear_readb(opaque, addr);
+ v |= cirrus_linear_readb(opaque, addr + 1) << 8;
+ v |= cirrus_linear_readb(opaque, addr + 2) << 16;
+ v |= cirrus_linear_readb(opaque, addr + 3) << 24;
+#endif
+ return v;
+}
+
+static void cirrus_linear_writeb(void *opaque, target_phys_addr_t addr,
+ uint32_t val)
+{
+ CirrusVGAState *s = (CirrusVGAState *) opaque;
+ unsigned mode;
+
+ addr &= s->cirrus_addr_mask;
+
+ if (((s->sr[0x17] & 0x44) == 0x44) &&
+ ((addr & s->linear_mmio_mask) == s->linear_mmio_mask)) {
+ /* memory-mapped I/O */
+ cirrus_mmio_blt_write(s, addr & 0xff, val);
+ } else if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
+ /* bitblt */
+ *s->cirrus_srcptr++ = (uint8_t) val;
+ if (s->cirrus_srcptr >= s->cirrus_srcptr_end) {
+ cirrus_bitblt_cputovideo_next(s);
+ }
+ } else {
+ /* video memory */
+ if ((s->gr[0x0B] & 0x14) == 0x14) {
+ addr <<= 4;
+ } else if (s->gr[0x0B] & 0x02) {
+ addr <<= 3;
+ }
+ addr &= s->cirrus_addr_mask;
+
+ mode = s->gr[0x05] & 0x7;
+ if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) {
+ *(s->vram_ptr + addr) = (uint8_t) val;
+ cpu_physical_memory_set_dirty(s->vram_offset + addr);
+ } else {
+ if ((s->gr[0x0B] & 0x14) != 0x14) {
+ cirrus_mem_writeb_mode4and5_8bpp(s, mode, addr, val);
+ } else {
+ cirrus_mem_writeb_mode4and5_16bpp(s, mode, addr, val);
+ }
+ }
+ }
+}
+
+static void cirrus_linear_writew(void *opaque, target_phys_addr_t addr,
+ uint32_t val)
+{
+#ifdef TARGET_WORDS_BIGENDIAN
+ cirrus_linear_writeb(opaque, addr, (val >> 8) & 0xff);
+ cirrus_linear_writeb(opaque, addr + 1, val & 0xff);
+#else
+ cirrus_linear_writeb(opaque, addr, val & 0xff);
+ cirrus_linear_writeb(opaque, addr + 1, (val >> 8) & 0xff);
+#endif
+}
+
+static void cirrus_linear_writel(void *opaque, target_phys_addr_t addr,
+ uint32_t val)
+{
+#ifdef TARGET_WORDS_BIGENDIAN
+ cirrus_linear_writeb(opaque, addr, (val >> 24) & 0xff);
+ cirrus_linear_writeb(opaque, addr + 1, (val >> 16) & 0xff);
+ cirrus_linear_writeb(opaque, addr + 2, (val >> 8) & 0xff);
+ cirrus_linear_writeb(opaque, addr + 3, val & 0xff);
+#else
+ cirrus_linear_writeb(opaque, addr, val & 0xff);
+ cirrus_linear_writeb(opaque, addr + 1, (val >> 8) & 0xff);
+ cirrus_linear_writeb(opaque, addr + 2, (val >> 16) & 0xff);
+ cirrus_linear_writeb(opaque, addr + 3, (val >> 24) & 0xff);
+#endif
+}
+
+
+static CPUReadMemoryFunc *cirrus_linear_read[3] = {
+ cirrus_linear_readb,
+ cirrus_linear_readw,
+ cirrus_linear_readl,
+};
+
+static CPUWriteMemoryFunc *cirrus_linear_write[3] = {
+ cirrus_linear_writeb,
+ cirrus_linear_writew,
+ cirrus_linear_writel,
+};
+
+static void cirrus_linear_mem_writeb(void *opaque, target_phys_addr_t addr,
+ uint32_t val)
+{
+ CirrusVGAState *s = (CirrusVGAState *) opaque;
+
+ addr &= s->cirrus_addr_mask;
+ *(s->vram_ptr + addr) = val;
+ cpu_physical_memory_set_dirty(s->vram_offset + addr);
+}
+
+static void cirrus_linear_mem_writew(void *opaque, target_phys_addr_t addr,
+ uint32_t val)
+{
+ CirrusVGAState *s = (CirrusVGAState *) opaque;
+
+ addr &= s->cirrus_addr_mask;
+ cpu_to_le16w((uint16_t *)(s->vram_ptr + addr), val);
+ cpu_physical_memory_set_dirty(s->vram_offset + addr);
+}
+
+static void cirrus_linear_mem_writel(void *opaque, target_phys_addr_t addr,
+ uint32_t val)
+{
+ CirrusVGAState *s = (CirrusVGAState *) opaque;
+
+ addr &= s->cirrus_addr_mask;
+ cpu_to_le32w((uint32_t *)(s->vram_ptr + addr), val);
+ cpu_physical_memory_set_dirty(s->vram_offset + addr);
+}
+
+/***************************************
+ *
+ * system to screen memory access
+ *
+ ***************************************/
+
+
+static uint32_t cirrus_linear_bitblt_readb(void *opaque, target_phys_addr_t addr)
+{
+ uint32_t ret;
+
+ /* XXX handle bitblt */
+ ret = 0xff;
+ return ret;
+}
+
+static uint32_t cirrus_linear_bitblt_readw(void *opaque, target_phys_addr_t addr)
+{
+ uint32_t v;
+#ifdef TARGET_WORDS_BIGENDIAN
+ v = cirrus_linear_bitblt_readb(opaque, addr) << 8;
+ v |= cirrus_linear_bitblt_readb(opaque, addr + 1);
+#else
+ v = cirrus_linear_bitblt_readb(opaque, addr);
+ v |= cirrus_linear_bitblt_readb(opaque, addr + 1) << 8;
+#endif
+ return v;
+}
+
+static uint32_t cirrus_linear_bitblt_readl(void *opaque, target_phys_addr_t addr)
+{
+ uint32_t v;
+#ifdef TARGET_WORDS_BIGENDIAN
+ v = cirrus_linear_bitblt_readb(opaque, addr) << 24;
+ v |= cirrus_linear_bitblt_readb(opaque, addr + 1) << 16;
+ v |= cirrus_linear_bitblt_readb(opaque, addr + 2) << 8;
+ v |= cirrus_linear_bitblt_readb(opaque, addr + 3);
+#else
+ v = cirrus_linear_bitblt_readb(opaque, addr);
+ v |= cirrus_linear_bitblt_readb(opaque, addr + 1) << 8;
+ v |= cirrus_linear_bitblt_readb(opaque, addr + 2) << 16;
+ v |= cirrus_linear_bitblt_readb(opaque, addr + 3) << 24;
+#endif
+ return v;
+}
+
+static void cirrus_linear_bitblt_writeb(void *opaque, target_phys_addr_t addr,
+ uint32_t val)
+{
+ CirrusVGAState *s = (CirrusVGAState *) opaque;
+
+ if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
+ /* bitblt */
+ *s->cirrus_srcptr++ = (uint8_t) val;
+ if (s->cirrus_srcptr >= s->cirrus_srcptr_end) {
+ cirrus_bitblt_cputovideo_next(s);
+ }
+ }
+}
+
+static void cirrus_linear_bitblt_writew(void *opaque, target_phys_addr_t addr,
+ uint32_t val)
+{
+#ifdef TARGET_WORDS_BIGENDIAN
+ cirrus_linear_bitblt_writeb(opaque, addr, (val >> 8) & 0xff);
+ cirrus_linear_bitblt_writeb(opaque, addr + 1, val & 0xff);
+#else
+ cirrus_linear_bitblt_writeb(opaque, addr, val & 0xff);
+ cirrus_linear_bitblt_writeb(opaque, addr + 1, (val >> 8) & 0xff);
+#endif
+}
+
+static void cirrus_linear_bitblt_writel(void *opaque, target_phys_addr_t addr,
+ uint32_t val)
+{
+#ifdef TARGET_WORDS_BIGENDIAN
+ cirrus_linear_bitblt_writeb(opaque, addr, (val >> 24) & 0xff);
+ cirrus_linear_bitblt_writeb(opaque, addr + 1, (val >> 16) & 0xff);
+ cirrus_linear_bitblt_writeb(opaque, addr + 2, (val >> 8) & 0xff);
+ cirrus_linear_bitblt_writeb(opaque, addr + 3, val & 0xff);
+#else
+ cirrus_linear_bitblt_writeb(opaque, addr, val & 0xff);
+ cirrus_linear_bitblt_writeb(opaque, addr + 1, (val >> 8) & 0xff);
+ cirrus_linear_bitblt_writeb(opaque, addr + 2, (val >> 16) & 0xff);
+ cirrus_linear_bitblt_writeb(opaque, addr + 3, (val >> 24) & 0xff);
+#endif
+}
+
+
+static CPUReadMemoryFunc *cirrus_linear_bitblt_read[3] = {
+ cirrus_linear_bitblt_readb,
+ cirrus_linear_bitblt_readw,
+ cirrus_linear_bitblt_readl,
+};
+
+static CPUWriteMemoryFunc *cirrus_linear_bitblt_write[3] = {
+ cirrus_linear_bitblt_writeb,
+ cirrus_linear_bitblt_writew,
+ cirrus_linear_bitblt_writel,
+};
+
+/* Compute the memory access functions */
+static void cirrus_update_memory_access(CirrusVGAState *s)
+{
+ unsigned mode;
+
+ if ((s->sr[0x17] & 0x44) == 0x44) {
+ goto generic_io;
+ } else if (s->cirrus_srcptr != s->cirrus_srcptr_end) {
+ goto generic_io;
+ } else {
+ if ((s->gr[0x0B] & 0x14) == 0x14) {
+ goto generic_io;
+ } else if (s->gr[0x0B] & 0x02) {
+ goto generic_io;
+ }
+
+ mode = s->gr[0x05] & 0x7;
+ if (mode < 4 || mode > 5 || ((s->gr[0x0B] & 0x4) == 0)) {
+ s->cirrus_linear_write[0] = cirrus_linear_mem_writeb;
+ s->cirrus_linear_write[1] = cirrus_linear_mem_writew;
+ s->cirrus_linear_write[2] = cirrus_linear_mem_writel;
+ } else {
+ generic_io:
+ s->cirrus_linear_write[0] = cirrus_linear_writeb;
+ s->cirrus_linear_write[1] = cirrus_linear_writew;
+ s->cirrus_linear_write[2] = cirrus_linear_writel;
+ }
+ }
+}
+
+
+/* I/O ports */
+
+static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
+{
+ CirrusVGAState *s = opaque;
+ int val, index;
+
+ /* check port range access depending on color/monochrome mode */
+ if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION))
+ || (addr >= 0x3d0 && addr <= 0x3df
+ && !(s->msr & MSR_COLOR_EMULATION))) {
+ val = 0xff;
+ } else {
+ switch (addr) {
+ case 0x3c0:
+ if (s->ar_flip_flop == 0) {
+ val = s->ar_index;
+ } else {
+ val = 0;
+ }
+ break;
+ case 0x3c1:
+ index = s->ar_index & 0x1f;
+ if (index < 21)
+ val = s->ar[index];
+ else
+ val = 0;
+ break;
+ case 0x3c2:
+ val = s->st00;
+ break;
+ case 0x3c4:
+ val = s->sr_index;
+ break;
+ case 0x3c5:
+ if (cirrus_hook_read_sr(s, s->sr_index, &val))
+ break;
+ val = s->sr[s->sr_index];
+#ifdef DEBUG_VGA_REG
+ printf("vga: read SR%x = 0x%02x\n", s->sr_index, val);
+#endif
+ break;
+ case 0x3c6:
+ cirrus_read_hidden_dac(s, &val);
+ break;
+ case 0x3c7:
+ val = s->dac_state;
+ break;
+ case 0x3c8:
+ val = s->dac_write_index;
+ s->cirrus_hidden_dac_lockindex = 0;
+ break;
+ case 0x3c9:
+ if (cirrus_hook_read_palette(s, &val))
+ break;
+ val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
+ if (++s->dac_sub_index == 3) {
+ s->dac_sub_index = 0;
+ s->dac_read_index++;
+ }
+ break;
+ case 0x3ca:
+ val = s->fcr;
+ break;
+ case 0x3cc:
+ val = s->msr;
+ break;
+ case 0x3ce:
+ val = s->gr_index;
+ break;
+ case 0x3cf:
+ if (cirrus_hook_read_gr(s, s->gr_index, &val))
+ break;
+ val = s->gr[s->gr_index];
+#ifdef DEBUG_VGA_REG
+ printf("vga: read GR%x = 0x%02x\n", s->gr_index, val);
+#endif
+ break;
+ case 0x3b4:
+ case 0x3d4:
+ val = s->cr_index;
+ break;
+ case 0x3b5:
+ case 0x3d5:
+ if (cirrus_hook_read_cr(s, s->cr_index, &val))
+ break;
+ val = s->cr[s->cr_index];
+#ifdef DEBUG_VGA_REG
+ printf("vga: read CR%x = 0x%02x\n", s->cr_index, val);
+#endif
+ break;
+ case 0x3ba:
+ case 0x3da:
+ /* just toggle to fool polling */
+ s->st01 ^= ST01_V_RETRACE | ST01_DISP_ENABLE;
+ val = s->st01;
+ s->ar_flip_flop = 0;
+ break;
+ default:
+ val = 0x00;
+ break;
+ }
+ }
+#if defined(DEBUG_VGA)
+ printf("VGA: read addr=0x%04x data=0x%02x\n", addr, val);
+#endif
+ return val;
+}
+
+static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
+{
+ CirrusVGAState *s = opaque;
+ int index;
+
+ /* check port range access depending on color/monochrome mode */
+ if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION))
+ || (addr >= 0x3d0 && addr <= 0x3df
+ && !(s->msr & MSR_COLOR_EMULATION)))
+ return;
+
+#ifdef DEBUG_VGA
+ printf("VGA: write addr=0x%04x data=0x%02x\n", addr, val);
+#endif
+
+ switch (addr) {
+ case 0x3c0:
+ if (s->ar_flip_flop == 0) {
+ val &= 0x3f;
+ s->ar_index = val;
+ } else {
+ index = s->ar_index & 0x1f;
+ switch (index) {
+ case 0x00 ... 0x0f:
+ s->ar[index] = val & 0x3f;
+ break;
+ case 0x10:
+ s->ar[index] = val & ~0x10;
+ break;
+ case 0x11:
+ s->ar[index] = val;
+ break;
+ case 0x12:
+ s->ar[index] = val & ~0xc0;
+ break;
+ case 0x13:
+ s->ar[index] = val & ~0xf0;
+ break;
+ case 0x14:
+ s->ar[index] = val & ~0xf0;
+ break;
+ default:
+ break;
+ }
+ }
+ s->ar_flip_flop ^= 1;
+ break;
+ case 0x3c2:
+ s->msr = val & ~0x10;
+ break;
+ case 0x3c4:
+ s->sr_index = val;
+ break;
+ case 0x3c5:
+ if (cirrus_hook_write_sr(s, s->sr_index, val))
+ break;
+#ifdef DEBUG_VGA_REG
+ printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
+#endif
+ s->sr[s->sr_index] = val & sr_mask[s->sr_index];
+ break;
+ case 0x3c6:
+ cirrus_write_hidden_dac(s, val);
+ break;
+ case 0x3c7:
+ s->dac_read_index = val;
+ s->dac_sub_index = 0;
+ s->dac_state = 3;
+ break;
+ case 0x3c8:
+ s->dac_write_index = val;
+ s->dac_sub_index = 0;
+ s->dac_state = 0;
+ break;
+ case 0x3c9:
+ if (cirrus_hook_write_palette(s, val))
+ break;
+ s->dac_cache[s->dac_sub_index] = val;
+ if (++s->dac_sub_index == 3) {
+ memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);
+ s->dac_sub_index = 0;
+ s->dac_write_index++;
+ }
+ break;
+ case 0x3ce:
+ s->gr_index = val;
+ break;
+ case 0x3cf:
+ if (cirrus_hook_write_gr(s, s->gr_index, val))
+ break;
+#ifdef DEBUG_VGA_REG
+ printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
+#endif
+ s->gr[s->gr_index] = val & gr_mask[s->gr_index];
+ break;
+ case 0x3b4:
+ case 0x3d4:
+ s->cr_index = val;
+ break;
+ case 0x3b5:
+ case 0x3d5:
+ if (cirrus_hook_write_cr(s, s->cr_index, val))
+ break;
+#ifdef DEBUG_VGA_REG
+ printf("vga: write CR%x = 0x%02x\n", s->cr_index, val);
+#endif
+ /* handle CR0-7 protection */
+ if ((s->cr[0x11] & 0x80) && s->cr_index <= 7) {
+ /* can always write bit 4 of CR7 */
+ if (s->cr_index == 7)
+ s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
+ return;
+ }
+ switch (s->cr_index) {
+ case 0x01: /* horizontal display end */
+ case 0x07:
+ case 0x09:
+ case 0x0c:
+ case 0x0d:
+ case 0x12: /* veritcal display end */
+ s->cr[s->cr_index] = val;
+ break;
+
+ default:
+ s->cr[s->cr_index] = val;
+ break;
+ }
+ break;
+ case 0x3ba:
+ case 0x3da:
+ s->fcr = val & 0x10;
+ break;
+ }
+}
+
+/***************************************
+ *
+ * memory-mapped I/O access
+ *
+ ***************************************/
+
+static uint32_t cirrus_mmio_readb(void *opaque, target_phys_addr_t addr)
+{
+ CirrusVGAState *s = (CirrusVGAState *) opaque;
+
+ addr &= CIRRUS_PNPMMIO_SIZE - 1;
+
+ if (addr >= 0x100) {
+ return cirrus_mmio_blt_read(s, addr - 0x100);
+ } else {
+ return vga_ioport_read(s, addr + 0x3c0);
+ }
+}
+
+static uint32_t cirrus_mmio_readw(void *opaque, target_phys_addr_t addr)
+{
+ uint32_t v;
+#ifdef TARGET_WORDS_BIGENDIAN
+ v = cirrus_mmio_readb(opaque, addr) << 8;
+ v |= cirrus_mmio_readb(opaque, addr + 1);
+#else
+ v = cirrus_mmio_readb(opaque, addr);
+ v |= cirrus_mmio_readb(opaque, addr + 1) << 8;
+#endif
+ return v;
+}
+
+static uint32_t cirrus_mmio_readl(void *opaque, target_phys_addr_t addr)
+{
+ uint32_t v;
+#ifdef TARGET_WORDS_BIGENDIAN
+ v = cirrus_mmio_readb(opaque, addr) << 24;
+ v |= cirrus_mmio_readb(opaque, addr + 1) << 16;
+ v |= cirrus_mmio_readb(opaque, addr + 2) << 8;
+ v |= cirrus_mmio_readb(opaque, addr + 3);
+#else
+ v = cirrus_mmio_readb(opaque, addr);
+ v |= cirrus_mmio_readb(opaque, addr + 1) << 8;
+ v |= cirrus_mmio_readb(opaque, addr + 2) << 16;
+ v |= cirrus_mmio_readb(opaque, addr + 3) << 24;
+#endif
+ return v;
+}
+
+static void cirrus_mmio_writeb(void *opaque, target_phys_addr_t addr,
+ uint32_t val)
+{
+ CirrusVGAState *s = (CirrusVGAState *) opaque;
+
+ addr &= CIRRUS_PNPMMIO_SIZE - 1;
+
+ if (addr >= 0x100) {
+ cirrus_mmio_blt_write(s, addr - 0x100, val);
+ } else {
+ vga_ioport_write(s, addr + 0x3c0, val);
+ }
+}
+
+static void cirrus_mmio_writew(void *opaque, target_phys_addr_t addr,
+ uint32_t val)
+{
+#ifdef TARGET_WORDS_BIGENDIAN
+ cirrus_mmio_writeb(opaque, addr, (val >> 8) & 0xff);
+ cirrus_mmio_writeb(opaque, addr + 1, val & 0xff);
+#else
+ cirrus_mmio_writeb(opaque, addr, val & 0xff);
+ cirrus_mmio_writeb(opaque, addr + 1, (val >> 8) & 0xff);
+#endif
+}
+
+static void cirrus_mmio_writel(void *opaque, target_phys_addr_t addr,
+ uint32_t val)
+{
+#ifdef TARGET_WORDS_BIGENDIAN
+ cirrus_mmio_writeb(opaque, addr, (val >> 24) & 0xff);
+ cirrus_mmio_writeb(opaque, addr + 1, (val >> 16) & 0xff);
+ cirrus_mmio_writeb(opaque, addr + 2, (val >> 8) & 0xff);
+ cirrus_mmio_writeb(opaque, addr + 3, val & 0xff);
+#else
+ cirrus_mmio_writeb(opaque, addr, val & 0xff);
+ cirrus_mmio_writeb(opaque, addr + 1, (val >> 8) & 0xff);
+ cirrus_mmio_writeb(opaque, addr + 2, (val >> 16) & 0xff);
+ cirrus_mmio_writeb(opaque, addr + 3, (val >> 24) & 0xff);
+#endif
+}
+
+
+static CPUReadMemoryFunc *cirrus_mmio_read[3] = {
+ cirrus_mmio_readb,
+ cirrus_mmio_readw,
+ cirrus_mmio_readl,
+};
+
+static CPUWriteMemoryFunc *cirrus_mmio_write[3] = {
+ cirrus_mmio_writeb,
+ cirrus_mmio_writew,
+ cirrus_mmio_writel,
+};
+
+/* load/save state */
+
+static void cirrus_vga_save(QEMUFile *f, void *opaque)
+{
+ CirrusVGAState *s = opaque;
+
+ qemu_put_be32s(f, &s->latch);
+ qemu_put_8s(f, &s->sr_index);
+ qemu_put_buffer(f, s->sr, 256);
+ qemu_put_8s(f, &s->gr_index);
+ qemu_put_8s(f, &s->cirrus_shadow_gr0);
+ qemu_put_8s(f, &s->cirrus_shadow_gr1);
+ qemu_put_buffer(f, s->gr + 2, 254);
+ qemu_put_8s(f, &s->ar_index);
+ qemu_put_buffer(f, s->ar, 21);
+ qemu_put_be32s(f, &s->ar_flip_flop);
+ qemu_put_8s(f, &s->cr_index);
+ qemu_put_buffer(f, s->cr, 256);
+ qemu_put_8s(f, &s->msr);
+ qemu_put_8s(f, &s->fcr);
+ qemu_put_8s(f, &s->st00);
+ qemu_put_8s(f, &s->st01);
+
+ qemu_put_8s(f, &s->dac_state);
+ qemu_put_8s(f, &s->dac_sub_index);
+ qemu_put_8s(f, &s->dac_read_index);
+ qemu_put_8s(f, &s->dac_write_index);
+ qemu_put_buffer(f, s->dac_cache, 3);
+ qemu_put_buffer(f, s->palette, 768);
+
+ qemu_put_be32s(f, &s->bank_offset);
+
+ qemu_put_8s(f, &s->cirrus_hidden_dac_lockindex);
+ qemu_put_8s(f, &s->cirrus_hidden_dac_data);
+
+ qemu_put_be32s(f, &s->hw_cursor_x);
+ qemu_put_be32s(f, &s->hw_cursor_y);
+ /* XXX: we do not save the bitblt state - we assume we do not save
+ the state when the blitter is active */
+}
+
+static int cirrus_vga_load(QEMUFile *f, void *opaque, int version_id)
+{
+ CirrusVGAState *s = opaque;
+
+ if (version_id != 1)
+ return -EINVAL;
+
+ qemu_get_be32s(f, &s->latch);
+ qemu_get_8s(f, &s->sr_index);
+ qemu_get_buffer(f, s->sr, 256);
+ qemu_get_8s(f, &s->gr_index);
+ qemu_get_8s(f, &s->cirrus_shadow_gr0);
+ qemu_get_8s(f, &s->cirrus_shadow_gr1);
+ s->gr[0x00] = s->cirrus_shadow_gr0 & 0x0f;
+ s->gr[0x01] = s->cirrus_shadow_gr1 & 0x0f;
+ qemu_get_buffer(f, s->gr + 2, 254);
+ qemu_get_8s(f, &s->ar_index);
+ qemu_get_buffer(f, s->ar, 21);
+ qemu_get_be32s(f, &s->ar_flip_flop);
+ qemu_get_8s(f, &s->cr_index);
+ qemu_get_buffer(f, s->cr, 256);
+ qemu_get_8s(f, &s->msr);
+ qemu_get_8s(f, &s->fcr);
+ qemu_get_8s(f, &s->st00);
+ qemu_get_8s(f, &s->st01);
+
+ qemu_get_8s(f, &s->dac_state);
+ qemu_get_8s(f, &s->dac_sub_index);
+ qemu_get_8s(f, &s->dac_read_index);
+ qemu_get_8s(f, &s->dac_write_index);
+ qemu_get_buffer(f, s->dac_cache, 3);
+ qemu_get_buffer(f, s->palette, 768);
+
+ qemu_get_be32s(f, &s->bank_offset);
+
+ qemu_get_8s(f, &s->cirrus_hidden_dac_lockindex);
+ qemu_get_8s(f, &s->cirrus_hidden_dac_data);
+
+ qemu_get_be32s(f, &s->hw_cursor_x);
+ qemu_get_be32s(f, &s->hw_cursor_y);
+
+ /* force refresh */
+ s->graphic_mode = -1;
+ cirrus_update_bank_ptr(s, 0);
+ cirrus_update_bank_ptr(s, 1);
+ return 0;
+}
+
+/***************************************
+ *
+ * initialize
+ *
+ ***************************************/
+
+static void cirrus_init_common(CirrusVGAState * s, int device_id, int is_pci)
+{
+ int vga_io_memory, i;
+ static int inited;
+
+ if (!inited) {
+ inited = 1;
+ for(i = 0;i < 256; i++)
+ rop_to_index[i] = CIRRUS_ROP_NOP_INDEX; /* nop rop */
+ rop_to_index[CIRRUS_ROP_0] = 0;
+ rop_to_index[CIRRUS_ROP_SRC_AND_DST] = 1;
+ rop_to_index[CIRRUS_ROP_NOP] = 2;
+ rop_to_index[CIRRUS_ROP_SRC_AND_NOTDST] = 3;
+ rop_to_index[CIRRUS_ROP_NOTDST] = 4;
+ rop_to_index[CIRRUS_ROP_SRC] = 5;
+ rop_to_index[CIRRUS_ROP_1] = 6;
+ rop_to_index[CIRRUS_ROP_NOTSRC_AND_DST] = 7;
+ rop_to_index[CIRRUS_ROP_SRC_XOR_DST] = 8;
+ rop_to_index[CIRRUS_ROP_SRC_OR_DST] = 9;
+ rop_to_index[CIRRUS_ROP_NOTSRC_OR_NOTDST] = 10;
+ rop_to_index[CIRRUS_ROP_SRC_NOTXOR_DST] = 11;
+ rop_to_index[CIRRUS_ROP_SRC_OR_NOTDST] = 12;
+ rop_to_index[CIRRUS_ROP_NOTSRC] = 13;
+ rop_to_index[CIRRUS_ROP_NOTSRC_OR_DST] = 14;
+ rop_to_index[CIRRUS_ROP_NOTSRC_AND_NOTDST] = 15;
+ }
+
+ register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
+
+ register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
+ register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
+ register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
+ register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
+
+ register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
+
+ register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
+ register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
+ register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
+ register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
+
+ vga_io_memory = cpu_register_io_memory(0, cirrus_vga_mem_read,
+ cirrus_vga_mem_write, s);
+ cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
+ vga_io_memory);
+
+ s->sr[0x06] = 0x0f;
+ if (device_id == CIRRUS_ID_CLGD5446) {
+ /* 4MB 64 bit memory config, always PCI */
+ s->sr[0x1F] = 0x2d; // MemClock
+ s->gr[0x18] = 0x0f; // fastest memory configuration
+#if 1
+ s->sr[0x0f] = 0x98;
+ s->sr[0x17] = 0x20;
+ s->sr[0x15] = 0x04; /* memory size, 3=2MB, 4=4MB */
+ s->real_vram_size = 4096 * 1024;
+#else
+ s->sr[0x0f] = 0x18;
+ s->sr[0x17] = 0x20;
+ s->sr[0x15] = 0x03; /* memory size, 3=2MB, 4=4MB */
+ s->real_vram_size = 2048 * 1024;
+#endif
+ } else {
+ s->sr[0x1F] = 0x22; // MemClock
+ s->sr[0x0F] = CIRRUS_MEMSIZE_2M;
+ if (is_pci)
+ s->sr[0x17] = CIRRUS_BUSTYPE_PCI;
+ else
+ s->sr[0x17] = CIRRUS_BUSTYPE_ISA;
+ s->real_vram_size = 2048 * 1024;
+ s->sr[0x15] = 0x03; /* memory size, 3=2MB, 4=4MB */
+ }
+ s->cr[0x27] = device_id;
+
+ /* Win2K seems to assume that the pattern buffer is at 0xff
+ initially ! */
+ memset(s->vram_ptr, 0xff, s->real_vram_size);
+
+ s->cirrus_hidden_dac_lockindex = 5;
+ s->cirrus_hidden_dac_data = 0;
+
+ /* I/O handler for LFB */
+ s->cirrus_linear_io_addr =
+ cpu_register_io_memory(0, cirrus_linear_read, cirrus_linear_write,
+ s);
+ s->cirrus_linear_write = cpu_get_io_memory_write(s->cirrus_linear_io_addr);
+
+ /* I/O handler for LFB */
+ s->cirrus_linear_bitblt_io_addr =
+ cpu_register_io_memory(0, cirrus_linear_bitblt_read, cirrus_linear_bitblt_write,
+ s);
+
+ /* I/O handler for memory-mapped I/O */
+ s->cirrus_mmio_io_addr =
+ cpu_register_io_memory(0, cirrus_mmio_read, cirrus_mmio_write, s);
+
+ /* XXX: s->vram_size must be a power of two */
+ s->cirrus_addr_mask = s->real_vram_size - 1;
+ s->linear_mmio_mask = s->real_vram_size - 256;
+
+ s->get_bpp = cirrus_get_bpp;
+ s->get_offsets = cirrus_get_offsets;
+ s->get_resolution = cirrus_get_resolution;
+ s->cursor_invalidate = cirrus_cursor_invalidate;
+ s->cursor_draw_line = cirrus_cursor_draw_line;
+
+ register_savevm("cirrus_vga", 0, 1, cirrus_vga_save, cirrus_vga_load, s);
+}
+
+/***************************************
+ *
+ * ISA bus support
+ *
+ ***************************************/
+
+void isa_cirrus_vga_init(DisplayState *ds, uint8_t *vga_ram_base,
+ unsigned long vga_ram_offset, int vga_ram_size)
+{
+ CirrusVGAState *s;
+
+ s = qemu_mallocz(sizeof(CirrusVGAState));
+
+ vga_common_init((VGAState *)s,
+ ds, vga_ram_base, vga_ram_offset, vga_ram_size);
+ cirrus_init_common(s, CIRRUS_ID_CLGD5430, 0);
+ /* XXX ISA-LFB support */
+}
+
+/***************************************
+ *
+ * PCI bus support
+ *
+ ***************************************/
+
+static void cirrus_pci_lfb_map(PCIDevice *d, int region_num,
+ uint32_t addr, uint32_t size, int type)
+{
+ CirrusVGAState *s = &((PCICirrusVGAState *)d)->cirrus_vga;
+
+ /* XXX: add byte swapping apertures */
+ cpu_register_physical_memory(addr, s->vram_size,
+ s->cirrus_linear_io_addr);
+ cpu_register_physical_memory(addr + 0x1000000, 0x400000,
+ s->cirrus_linear_bitblt_io_addr);
+}
+
+static void cirrus_pci_mmio_map(PCIDevice *d, int region_num,
+ uint32_t addr, uint32_t size, int type)
+{
+ CirrusVGAState *s = &((PCICirrusVGAState *)d)->cirrus_vga;
+
+ cpu_register_physical_memory(addr, CIRRUS_PNPMMIO_SIZE,
+ s->cirrus_mmio_io_addr);
+}
+
+void pci_cirrus_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
+ unsigned long vga_ram_offset, int vga_ram_size)
+{
+ PCICirrusVGAState *d;
+ uint8_t *pci_conf;
+ CirrusVGAState *s;
+ int device_id;
+
+ device_id = CIRRUS_ID_CLGD5446;
+
+ /* setup PCI configuration registers */
+ d = (PCICirrusVGAState *)pci_register_device(bus, "Cirrus VGA",
+ sizeof(PCICirrusVGAState),
+ -1, NULL, NULL);
+ pci_conf = d->dev.config;
+ pci_conf[0x00] = (uint8_t) (PCI_VENDOR_CIRRUS & 0xff);
+ pci_conf[0x01] = (uint8_t) (PCI_VENDOR_CIRRUS >> 8);
+ pci_conf[0x02] = (uint8_t) (device_id & 0xff);
+ pci_conf[0x03] = (uint8_t) (device_id >> 8);
+ pci_conf[0x04] = PCI_COMMAND_IOACCESS | PCI_COMMAND_MEMACCESS;
+ pci_conf[0x0a] = PCI_CLASS_SUB_VGA;
+ pci_conf[0x0b] = PCI_CLASS_BASE_DISPLAY;
+ pci_conf[0x0e] = PCI_CLASS_HEADERTYPE_00h;
+
+ /* setup VGA */
+ s = &d->cirrus_vga;
+ vga_common_init((VGAState *)s,
+ ds, vga_ram_base, vga_ram_offset, vga_ram_size);
+ cirrus_init_common(s, device_id, 1);
+
+ /* setup memory space */
+ /* memory #0 LFB */
+ /* memory #1 memory-mapped I/O */
+ /* XXX: s->vram_size must be a power of two */
+ pci_register_io_region((PCIDevice *)d, 0, 0x2000000,
+ PCI_ADDRESS_SPACE_MEM_PREFETCH, cirrus_pci_lfb_map);
+ if (device_id == CIRRUS_ID_CLGD5446) {
+ pci_register_io_region((PCIDevice *)d, 1, CIRRUS_PNPMMIO_SIZE,
+ PCI_ADDRESS_SPACE_MEM, cirrus_pci_mmio_map);
+ }
+ /* XXX: ROM BIOS */
+}
--- /dev/null
+/*
+ * QEMU Cirrus CLGD 54xx VGA Emulator.
+ *
+ * Copyright (c) 2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+static void
+glue(cirrus_bitblt_rop_fwd_, ROP_NAME)(CirrusVGAState *s,
+ uint8_t *dst,const uint8_t *src,
+ int dstpitch,int srcpitch,
+ int bltwidth,int bltheight)
+{
+ int x,y;
+ dstpitch -= bltwidth;
+ srcpitch -= bltwidth;
+ for (y = 0; y < bltheight; y++) {
+ for (x = 0; x < bltwidth; x++) {
+ ROP_OP(*dst, *src);
+ dst++;
+ src++;
+ }
+ dst += dstpitch;
+ src += srcpitch;
+ }
+}
+
+static void
+glue(cirrus_bitblt_rop_bkwd_, ROP_NAME)(CirrusVGAState *s,
+ uint8_t *dst,const uint8_t *src,
+ int dstpitch,int srcpitch,
+ int bltwidth,int bltheight)
+{
+ int x,y;
+ dstpitch += bltwidth;
+ srcpitch += bltwidth;
+ for (y = 0; y < bltheight; y++) {
+ for (x = 0; x < bltwidth; x++) {
+ ROP_OP(*dst, *src);
+ dst--;
+ src--;
+ }
+ dst += dstpitch;
+ src += srcpitch;
+ }
+}
+
+#define DEPTH 8
+#include "cirrus_vga_rop2.h"
+
+#define DEPTH 16
+#include "cirrus_vga_rop2.h"
+
+#define DEPTH 24
+#include "cirrus_vga_rop2.h"
+
+#define DEPTH 32
+#include "cirrus_vga_rop2.h"
+
+#undef ROP_NAME
+#undef ROP_OP
--- /dev/null
+/*
+ * QEMU Cirrus CLGD 54xx VGA Emulator.
+ *
+ * Copyright (c) 2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#if DEPTH == 8
+#define PUTPIXEL() ROP_OP(d[0], col)
+#elif DEPTH == 16
+#define PUTPIXEL() ROP_OP(((uint16_t *)d)[0], col);
+#elif DEPTH == 24
+#define PUTPIXEL() ROP_OP(d[0], col); \
+ ROP_OP(d[1], (col >> 8)); \
+ ROP_OP(d[2], (col >> 16))
+#elif DEPTH == 32
+#define PUTPIXEL() ROP_OP(((uint32_t *)d)[0], col)
+#else
+#error unsupported DEPTH
+#endif
+
+static void
+glue(glue(glue(cirrus_patternfill_, ROP_NAME), _),DEPTH)
+ (CirrusVGAState * s, uint8_t * dst,
+ const uint8_t * src,
+ int dstpitch, int srcpitch,
+ int bltwidth, int bltheight)
+{
+ uint8_t *d;
+ int x, y, pattern_y, pattern_pitch, pattern_x;
+ unsigned int col;
+ const uint8_t *src1;
+
+#if DEPTH == 8
+ pattern_pitch = 8;
+#elif DEPTH == 16
+ pattern_pitch = 16;
+#else
+ pattern_pitch = 32;
+#endif
+ pattern_y = s->cirrus_blt_srcaddr & 7;
+ pattern_x = 0;
+ for(y = 0; y < bltheight; y++) {
+ d = dst;
+ src1 = src + pattern_y * pattern_pitch;
+ for (x = 0; x < bltwidth; x += (DEPTH / 8)) {
+#if DEPTH == 8
+ col = src1[pattern_x];
+ pattern_x = (pattern_x + 1) & 7;
+#elif DEPTH == 16
+ col = ((uint16_t *)(src1 + pattern_x))[0];
+ pattern_x = (pattern_x + 2) & 15;
+#elif DEPTH == 24
+ {
+ const uint8_t *src2 = src1 + pattern_x * 3;
+ col = src2[0] | (src2[1] << 8) | (src2[2] << 16);
+ pattern_x = (pattern_x + 1) & 7;
+ }
+#else
+ col = ((uint32_t *)(src1 + pattern_x))[0];
+ pattern_x = (pattern_x + 4) & 31;
+#endif
+ PUTPIXEL();
+ d += (DEPTH / 8);
+ }
+ pattern_y = (pattern_y + 1) & 7;
+ dst += dstpitch;
+ }
+}
+
+/* NOTE: srcpitch is ignored */
+static void
+glue(glue(glue(cirrus_colorexpand_transp_, ROP_NAME), _),DEPTH)
+ (CirrusVGAState * s, uint8_t * dst,
+ const uint8_t * src,
+ int dstpitch, int srcpitch,
+ int bltwidth, int bltheight)
+{
+ uint8_t *d;
+ int x, y;
+ unsigned bits, bits_xor;
+ unsigned int col;
+ unsigned bitmask;
+ unsigned index;
+ int srcskipleft = 0;
+
+ if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) {
+ bits_xor = 0xff;
+ col = s->cirrus_blt_bgcol;
+ } else {
+ bits_xor = 0x00;
+ col = s->cirrus_blt_fgcol;
+ }
+
+ for(y = 0; y < bltheight; y++) {
+ bitmask = 0x80 >> srcskipleft;
+ bits = *src++ ^ bits_xor;
+ d = dst;
+ for (x = 0; x < bltwidth; x += (DEPTH / 8)) {
+ if ((bitmask & 0xff) == 0) {
+ bitmask = 0x80;
+ bits = *src++ ^ bits_xor;
+ }
+ index = (bits & bitmask);
+ if (index) {
+ PUTPIXEL();
+ }
+ d += (DEPTH / 8);
+ bitmask >>= 1;
+ }
+ dst += dstpitch;
+ }
+}
+
+static void
+glue(glue(glue(cirrus_colorexpand_, ROP_NAME), _),DEPTH)
+ (CirrusVGAState * s, uint8_t * dst,
+ const uint8_t * src,
+ int dstpitch, int srcpitch,
+ int bltwidth, int bltheight)
+{
+ uint32_t colors[2];
+ uint8_t *d;
+ int x, y;
+ unsigned bits;
+ unsigned int col;
+ unsigned bitmask;
+ int srcskipleft = 0;
+
+ colors[0] = s->cirrus_blt_bgcol;
+ colors[1] = s->cirrus_blt_fgcol;
+ for(y = 0; y < bltheight; y++) {
+ bitmask = 0x80 >> srcskipleft;
+ bits = *src++;
+ d = dst;
+ for (x = 0; x < bltwidth; x += (DEPTH / 8)) {
+ if ((bitmask & 0xff) == 0) {
+ bitmask = 0x80;
+ bits = *src++;
+ }
+ col = colors[!!(bits & bitmask)];
+ PUTPIXEL();
+ d += (DEPTH / 8);
+ bitmask >>= 1;
+ }
+ dst += dstpitch;
+ }
+}
+
+static void
+glue(glue(glue(cirrus_colorexpand_pattern_transp_, ROP_NAME), _),DEPTH)
+ (CirrusVGAState * s, uint8_t * dst,
+ const uint8_t * src,
+ int dstpitch, int srcpitch,
+ int bltwidth, int bltheight)
+{
+ uint8_t *d;
+ int x, y, bitpos, pattern_y;
+ unsigned int bits, bits_xor;
+ unsigned int col;
+
+ if (s->cirrus_blt_modeext & CIRRUS_BLTMODEEXT_COLOREXPINV) {
+ bits_xor = 0xff;
+ col = s->cirrus_blt_bgcol;
+ } else {
+ bits_xor = 0x00;
+ col = s->cirrus_blt_fgcol;
+ }
+ pattern_y = s->cirrus_blt_srcaddr & 7;
+
+ for(y = 0; y < bltheight; y++) {
+ bits = src[pattern_y] ^ bits_xor;
+ bitpos = 7;
+ d = dst;
+ for (x = 0; x < bltwidth; x += (DEPTH / 8)) {
+ if ((bits >> bitpos) & 1) {
+ PUTPIXEL();
+ }
+ d += (DEPTH / 8);
+ bitpos = (bitpos - 1) & 7;
+ }
+ pattern_y = (pattern_y + 1) & 7;
+ dst += dstpitch;
+ }
+}
+
+static void
+glue(glue(glue(cirrus_colorexpand_pattern_, ROP_NAME), _),DEPTH)
+ (CirrusVGAState * s, uint8_t * dst,
+ const uint8_t * src,
+ int dstpitch, int srcpitch,
+ int bltwidth, int bltheight)
+{
+ uint32_t colors[2];
+ uint8_t *d;
+ int x, y, bitpos, pattern_y;
+ unsigned int bits;
+ unsigned int col;
+
+ colors[0] = s->cirrus_blt_bgcol;
+ colors[1] = s->cirrus_blt_fgcol;
+ pattern_y = s->cirrus_blt_srcaddr & 7;
+
+ for(y = 0; y < bltheight; y++) {
+ bits = src[pattern_y];
+ bitpos = 7;
+ d = dst;
+ for (x = 0; x < bltwidth; x += (DEPTH / 8)) {
+ col = colors[(bits >> bitpos) & 1];
+ PUTPIXEL();
+ d += (DEPTH / 8);
+ bitpos = (bitpos - 1) & 7;
+ }
+ pattern_y = (pattern_y + 1) & 7;
+ dst += dstpitch;
+ }
+}
+
+static void
+glue(glue(glue(cirrus_fill_, ROP_NAME), _),DEPTH)
+ (CirrusVGAState *s,
+ uint8_t *dst, int dst_pitch,
+ int width, int height)
+{
+ uint8_t *d, *d1;
+ uint32_t col;
+ int x, y;
+
+ col = s->cirrus_blt_fgcol;
+
+ d1 = dst;
+ for(y = 0; y < height; y++) {
+ d = d1;
+ for(x = 0; x < width; x += (DEPTH / 8)) {
+ PUTPIXEL();
+ d += (DEPTH / 8);
+ }
+ d1 += dst_pitch;
+ }
+}
+
+#undef DEPTH
+#undef PUTPIXEL
--- /dev/null
+/*
+ * QEMU CUDA support
+ *
+ * Copyright (c) 2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+
+//#define DEBUG_CUDA
+//#define DEBUG_CUDA_PACKET
+
+/* Bits in B data register: all active low */
+#define TREQ 0x08 /* Transfer request (input) */
+#define TACK 0x10 /* Transfer acknowledge (output) */
+#define TIP 0x20 /* Transfer in progress (output) */
+
+/* Bits in ACR */
+#define SR_CTRL 0x1c /* Shift register control bits */
+#define SR_EXT 0x0c /* Shift on external clock */
+#define SR_OUT 0x10 /* Shift out if 1 */
+
+/* Bits in IFR and IER */
+#define IER_SET 0x80 /* set bits in IER */
+#define IER_CLR 0 /* clear bits in IER */
+#define SR_INT 0x04 /* Shift register full/empty */
+#define T1_INT 0x40 /* Timer 1 interrupt */
+
+/* Bits in ACR */
+#define T1MODE 0xc0 /* Timer 1 mode */
+#define T1MODE_CONT 0x40 /* continuous interrupts */
+
+/* commands (1st byte) */
+#define ADB_PACKET 0
+#define CUDA_PACKET 1
+#define ERROR_PACKET 2
+#define TIMER_PACKET 3
+#define POWER_PACKET 4
+#define MACIIC_PACKET 5
+#define PMU_PACKET 6
+
+
+/* CUDA commands (2nd byte) */
+#define CUDA_WARM_START 0x0
+#define CUDA_AUTOPOLL 0x1
+#define CUDA_GET_6805_ADDR 0x2
+#define CUDA_GET_TIME 0x3
+#define CUDA_GET_PRAM 0x7
+#define CUDA_SET_6805_ADDR 0x8
+#define CUDA_SET_TIME 0x9
+#define CUDA_POWERDOWN 0xa
+#define CUDA_POWERUP_TIME 0xb
+#define CUDA_SET_PRAM 0xc
+#define CUDA_MS_RESET 0xd
+#define CUDA_SEND_DFAC 0xe
+#define CUDA_BATTERY_SWAP_SENSE 0x10
+#define CUDA_RESET_SYSTEM 0x11
+#define CUDA_SET_IPL 0x12
+#define CUDA_FILE_SERVER_FLAG 0x13
+#define CUDA_SET_AUTO_RATE 0x14
+#define CUDA_GET_AUTO_RATE 0x16
+#define CUDA_SET_DEVICE_LIST 0x19
+#define CUDA_GET_DEVICE_LIST 0x1a
+#define CUDA_SET_ONE_SECOND_MODE 0x1b
+#define CUDA_SET_POWER_MESSAGES 0x21
+#define CUDA_GET_SET_IIC 0x22
+#define CUDA_WAKEUP 0x23
+#define CUDA_TIMER_TICKLE 0x24
+#define CUDA_COMBINED_FORMAT_IIC 0x25
+
+#define CUDA_TIMER_FREQ (4700000 / 6)
+#define CUDA_ADB_POLL_FREQ 50
+
+typedef struct CUDATimer {
+ unsigned int latch;
+ uint16_t counter_value; /* counter value at load time */
+ int64_t load_time;
+ int64_t next_irq_time;
+ QEMUTimer *timer;
+} CUDATimer;
+
+typedef struct CUDAState {
+ /* cuda registers */
+ uint8_t b; /* B-side data */
+ uint8_t a; /* A-side data */
+ uint8_t dirb; /* B-side direction (1=output) */
+ uint8_t dira; /* A-side direction (1=output) */
+ uint8_t sr; /* Shift register */
+ uint8_t acr; /* Auxiliary control register */
+ uint8_t pcr; /* Peripheral control register */
+ uint8_t ifr; /* Interrupt flag register */
+ uint8_t ier; /* Interrupt enable register */
+ uint8_t anh; /* A-side data, no handshake */
+
+ CUDATimer timers[2];
+
+ uint8_t last_b; /* last value of B register */
+ uint8_t last_acr; /* last value of B register */
+
+ int data_in_size;
+ int data_in_index;
+ int data_out_index;
+
+ int irq;
+ openpic_t *openpic;
+ uint8_t autopoll;
+ uint8_t data_in[128];
+ uint8_t data_out[16];
+ QEMUTimer *adb_poll_timer;
+} CUDAState;
+
+static CUDAState cuda_state;
+ADBBusState adb_bus;
+
+static void cuda_update(CUDAState *s);
+static void cuda_receive_packet_from_host(CUDAState *s,
+ const uint8_t *data, int len);
+static void cuda_timer_update(CUDAState *s, CUDATimer *ti,
+ int64_t current_time);
+
+static void cuda_update_irq(CUDAState *s)
+{
+ if (s->ifr & s->ier & (SR_INT | T1_INT)) {
+ openpic_set_irq(s->openpic, s->irq, 1);
+ } else {
+ openpic_set_irq(s->openpic, s->irq, 0);
+ }
+}
+
+static unsigned int get_counter(CUDATimer *s)
+{
+ int64_t d;
+ unsigned int counter;
+
+ d = muldiv64(qemu_get_clock(vm_clock) - s->load_time,
+ CUDA_TIMER_FREQ, ticks_per_sec);
+ if (d <= s->counter_value) {
+ counter = d;
+ } else {
+ counter = s->latch - 1 - ((d - s->counter_value) % s->latch);
+ }
+ return counter;
+}
+
+static void set_counter(CUDAState *s, CUDATimer *ti, unsigned int val)
+{
+#ifdef DEBUG_CUDA
+ printf("cuda: T%d.counter=%d\n",
+ 1 + (ti->timer == NULL), val);
+#endif
+ ti->load_time = qemu_get_clock(vm_clock);
+ ti->counter_value = val;
+ cuda_timer_update(s, ti, ti->load_time);
+}
+
+static int64_t get_next_irq_time(CUDATimer *s, int64_t current_time)
+{
+ int64_t d, next_time, base;
+ /* current counter value */
+ d = muldiv64(current_time - s->load_time,
+ CUDA_TIMER_FREQ, ticks_per_sec);
+ if (d <= s->counter_value) {
+ next_time = s->counter_value + 1;
+ } else {
+ base = ((d - s->counter_value) / s->latch);
+ base = (base * s->latch) + s->counter_value;
+ next_time = base + s->latch;
+ }
+#ifdef DEBUG_CUDA
+ printf("latch=%d counter=%lld delta_next=%lld\n",
+ s->latch, d, next_time - d);
+#endif
+ next_time = muldiv64(next_time, ticks_per_sec, CUDA_TIMER_FREQ) +
+ s->load_time;
+ if (next_time <= current_time)
+ next_time = current_time + 1;
+ return next_time;
+}
+
+static void cuda_timer_update(CUDAState *s, CUDATimer *ti,
+ int64_t current_time)
+{
+ if (!ti->timer)
+ return;
+ if ((s->acr & T1MODE) != T1MODE_CONT) {
+ qemu_del_timer(ti->timer);
+ } else {
+ ti->next_irq_time = get_next_irq_time(ti, current_time);
+ qemu_mod_timer(ti->timer, ti->next_irq_time);
+ }
+}
+
+static void cuda_timer1(void *opaque)
+{
+ CUDAState *s = opaque;
+ CUDATimer *ti = &s->timers[0];
+
+ cuda_timer_update(s, ti, ti->next_irq_time);
+ s->ifr |= T1_INT;
+ cuda_update_irq(s);
+}
+
+static uint32_t cuda_readb(void *opaque, target_phys_addr_t addr)
+{
+ CUDAState *s = opaque;
+ uint32_t val;
+
+ addr = (addr >> 9) & 0xf;
+ switch(addr) {
+ case 0:
+ val = s->b;
+ break;
+ case 1:
+ val = s->a;
+ break;
+ case 2:
+ val = s->dirb;
+ break;
+ case 3:
+ val = s->dira;
+ break;
+ case 4:
+ val = get_counter(&s->timers[0]) & 0xff;
+ s->ifr &= ~T1_INT;
+ cuda_update_irq(s);
+ break;
+ case 5:
+ val = get_counter(&s->timers[0]) >> 8;
+ s->ifr &= ~T1_INT;
+ cuda_update_irq(s);
+ break;
+ case 6:
+ val = s->timers[0].latch & 0xff;
+ break;
+ case 7:
+ val = (s->timers[0].latch >> 8) & 0xff;
+ break;
+ case 8:
+ val = get_counter(&s->timers[1]) & 0xff;
+ break;
+ case 9:
+ val = get_counter(&s->timers[1]) >> 8;
+ break;
+ case 10:
+ val = s->sr;
+ s->ifr &= ~SR_INT;
+ cuda_update_irq(s);
+ break;
+ case 11:
+ val = s->acr;
+ break;
+ case 12:
+ val = s->pcr;
+ break;
+ case 13:
+ val = s->ifr;
+ break;
+ case 14:
+ val = s->ier;
+ break;
+ default:
+ case 15:
+ val = s->anh;
+ break;
+ }
+#ifdef DEBUG_CUDA
+ if (addr != 13 || val != 0)
+ printf("cuda: read: reg=0x%x val=%02x\n", addr, val);
+#endif
+ return val;
+}
+
+static void cuda_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ CUDAState *s = opaque;
+
+ addr = (addr >> 9) & 0xf;
+#ifdef DEBUG_CUDA
+ printf("cuda: write: reg=0x%x val=%02x\n", addr, val);
+#endif
+
+ switch(addr) {
+ case 0:
+ s->b = val;
+ cuda_update(s);
+ break;
+ case 1:
+ s->a = val;
+ break;
+ case 2:
+ s->dirb = val;
+ break;
+ case 3:
+ s->dira = val;
+ break;
+ case 4:
+ val = val | (get_counter(&s->timers[0]) & 0xff00);
+ set_counter(s, &s->timers[0], val);
+ break;
+ case 5:
+ val = (val << 8) | (get_counter(&s->timers[0]) & 0xff);
+ set_counter(s, &s->timers[0], val);
+ break;
+ case 6:
+ s->timers[0].latch = (s->timers[0].latch & 0xff00) | val;
+ cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock));
+ break;
+ case 7:
+ s->timers[0].latch = (s->timers[0].latch & 0xff) | (val << 8);
+ cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock));
+ break;
+ case 8:
+ val = val | (get_counter(&s->timers[1]) & 0xff00);
+ set_counter(s, &s->timers[1], val);
+ break;
+ case 9:
+ val = (val << 8) | (get_counter(&s->timers[1]) & 0xff);
+ set_counter(s, &s->timers[1], val);
+ break;
+ case 10:
+ s->sr = val;
+ break;
+ case 11:
+ s->acr = val;
+ cuda_timer_update(s, &s->timers[0], qemu_get_clock(vm_clock));
+ cuda_update(s);
+ break;
+ case 12:
+ s->pcr = val;
+ break;
+ case 13:
+ /* reset bits */
+ s->ifr &= ~val;
+ cuda_update_irq(s);
+ break;
+ case 14:
+ if (val & IER_SET) {
+ /* set bits */
+ s->ier |= val & 0x7f;
+ } else {
+ /* reset bits */
+ s->ier &= ~val;
+ }
+ cuda_update_irq(s);
+ break;
+ default:
+ case 15:
+ s->anh = val;
+ break;
+ }
+}
+
+/* NOTE: TIP and TREQ are negated */
+static void cuda_update(CUDAState *s)
+{
+ int packet_received, len;
+
+ packet_received = 0;
+ if (!(s->b & TIP)) {
+ /* transfer requested from host */
+
+ if (s->acr & SR_OUT) {
+ /* data output */
+ if ((s->b & (TACK | TIP)) != (s->last_b & (TACK | TIP))) {
+ if (s->data_out_index < sizeof(s->data_out)) {
+#ifdef DEBUG_CUDA
+ printf("cuda: send: %02x\n", s->sr);
+#endif
+ s->data_out[s->data_out_index++] = s->sr;
+ s->ifr |= SR_INT;
+ cuda_update_irq(s);
+ }
+ }
+ } else {
+ if (s->data_in_index < s->data_in_size) {
+ /* data input */
+ if ((s->b & (TACK | TIP)) != (s->last_b & (TACK | TIP))) {
+ s->sr = s->data_in[s->data_in_index++];
+#ifdef DEBUG_CUDA
+ printf("cuda: recv: %02x\n", s->sr);
+#endif
+ /* indicate end of transfer */
+ if (s->data_in_index >= s->data_in_size) {
+ s->b = (s->b | TREQ);
+ }
+ s->ifr |= SR_INT;
+ cuda_update_irq(s);
+ }
+ }
+ }
+ } else {
+ /* no transfer requested: handle sync case */
+ if ((s->last_b & TIP) && (s->b & TACK) != (s->last_b & TACK)) {
+ /* update TREQ state each time TACK change state */
+ if (s->b & TACK)
+ s->b = (s->b | TREQ);
+ else
+ s->b = (s->b & ~TREQ);
+ s->ifr |= SR_INT;
+ cuda_update_irq(s);
+ } else {
+ if (!(s->last_b & TIP)) {
+ /* handle end of host to cuda transfert */
+ packet_received = (s->data_out_index > 0);
+ /* always an IRQ at the end of transfert */
+ s->ifr |= SR_INT;
+ cuda_update_irq(s);
+ }
+ /* signal if there is data to read */
+ if (s->data_in_index < s->data_in_size) {
+ s->b = (s->b & ~TREQ);
+ }
+ }
+ }
+
+ s->last_acr = s->acr;
+ s->last_b = s->b;
+
+ /* NOTE: cuda_receive_packet_from_host() can call cuda_update()
+ recursively */
+ if (packet_received) {
+ len = s->data_out_index;
+ s->data_out_index = 0;
+ cuda_receive_packet_from_host(s, s->data_out, len);
+ }
+}
+
+static void cuda_send_packet_to_host(CUDAState *s,
+ const uint8_t *data, int len)
+{
+#ifdef DEBUG_CUDA_PACKET
+ {
+ int i;
+ printf("cuda_send_packet_to_host:\n");
+ for(i = 0; i < len; i++)
+ printf(" %02x", data[i]);
+ printf("\n");
+ }
+#endif
+ memcpy(s->data_in, data, len);
+ s->data_in_size = len;
+ s->data_in_index = 0;
+ cuda_update(s);
+ s->ifr |= SR_INT;
+ cuda_update_irq(s);
+}
+
+static void cuda_adb_poll(void *opaque)
+{
+ CUDAState *s = opaque;
+ uint8_t obuf[ADB_MAX_OUT_LEN + 2];
+ int olen;
+
+ olen = adb_poll(&adb_bus, obuf + 2);
+ if (olen > 0) {
+ obuf[0] = ADB_PACKET;
+ obuf[1] = 0x40; /* polled data */
+ cuda_send_packet_to_host(s, obuf, olen + 2);
+ }
+ qemu_mod_timer(s->adb_poll_timer,
+ qemu_get_clock(vm_clock) +
+ (ticks_per_sec / CUDA_ADB_POLL_FREQ));
+}
+
+static void cuda_receive_packet(CUDAState *s,
+ const uint8_t *data, int len)
+{
+ uint8_t obuf[16];
+ int ti, autopoll;
+
+ switch(data[0]) {
+ case CUDA_AUTOPOLL:
+ autopoll = (data[1] != 0);
+ if (autopoll != s->autopoll) {
+ s->autopoll = autopoll;
+ if (autopoll) {
+ qemu_mod_timer(s->adb_poll_timer,
+ qemu_get_clock(vm_clock) +
+ (ticks_per_sec / CUDA_ADB_POLL_FREQ));
+ } else {
+ qemu_del_timer(s->adb_poll_timer);
+ }
+ }
+ obuf[0] = CUDA_PACKET;
+ obuf[1] = data[1];
+ cuda_send_packet_to_host(s, obuf, 2);
+ break;
+ case CUDA_GET_TIME:
+ /* XXX: add time support ? */
+ ti = time(NULL);
+ obuf[0] = CUDA_PACKET;
+ obuf[1] = 0;
+ obuf[2] = 0;
+ obuf[3] = ti >> 24;
+ obuf[4] = ti >> 16;
+ obuf[5] = ti >> 8;
+ obuf[6] = ti;
+ cuda_send_packet_to_host(s, obuf, 7);
+ break;
+ case CUDA_SET_TIME:
+ case CUDA_FILE_SERVER_FLAG:
+ case CUDA_SET_DEVICE_LIST:
+ case CUDA_SET_AUTO_RATE:
+ case CUDA_SET_POWER_MESSAGES:
+ obuf[0] = CUDA_PACKET;
+ obuf[1] = 0;
+ cuda_send_packet_to_host(s, obuf, 2);
+ break;
+ default:
+ break;
+ }
+}
+
+static void cuda_receive_packet_from_host(CUDAState *s,
+ const uint8_t *data, int len)
+{
+#ifdef DEBUG_CUDA_PACKET
+ {
+ int i;
+ printf("cuda_receive_packet_to_host:\n");
+ for(i = 0; i < len; i++)
+ printf(" %02x", data[i]);
+ printf("\n");
+ }
+#endif
+ switch(data[0]) {
+ case ADB_PACKET:
+ {
+ uint8_t obuf[ADB_MAX_OUT_LEN + 2];
+ int olen;
+ olen = adb_request(&adb_bus, obuf + 2, data + 1, len - 1);
+ if (olen > 0) {
+ obuf[0] = ADB_PACKET;
+ obuf[1] = 0x00;
+ } else {
+ /* error */
+ obuf[0] = ADB_PACKET;
+ obuf[1] = -olen;
+ olen = 0;
+ }
+ cuda_send_packet_to_host(s, obuf, olen + 2);
+ }
+ break;
+ case CUDA_PACKET:
+ cuda_receive_packet(s, data + 1, len - 1);
+ break;
+ }
+}
+
+static void cuda_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+}
+
+static void cuda_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+}
+
+static uint32_t cuda_readw (void *opaque, target_phys_addr_t addr)
+{
+ return 0;
+}
+
+static uint32_t cuda_readl (void *opaque, target_phys_addr_t addr)
+{
+ return 0;
+}
+
+static CPUWriteMemoryFunc *cuda_write[] = {
+ &cuda_writeb,
+ &cuda_writew,
+ &cuda_writel,
+};
+
+static CPUReadMemoryFunc *cuda_read[] = {
+ &cuda_readb,
+ &cuda_readw,
+ &cuda_readl,
+};
+
+int cuda_init(openpic_t *openpic, int irq)
+{
+ CUDAState *s = &cuda_state;
+ int cuda_mem_index;
+
+ s->openpic = openpic;
+ s->irq = irq;
+
+ s->timers[0].timer = qemu_new_timer(vm_clock, cuda_timer1, s);
+ s->timers[0].latch = 0x10000;
+ set_counter(s, &s->timers[0], 0xffff);
+ s->timers[1].latch = 0x10000;
+ s->ier = T1_INT | SR_INT;
+ set_counter(s, &s->timers[1], 0xffff);
+
+ s->adb_poll_timer = qemu_new_timer(vm_clock, cuda_adb_poll, s);
+ cuda_mem_index = cpu_register_io_memory(0, cuda_read, cuda_write, s);
+ return cuda_mem_index;
+}
--- /dev/null
+/*
+ * QEMU DMA emulation
+ *
+ * Copyright (c) 2003-2004 Vassili Karpov (malc)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+
+/* #define DEBUG_DMA */
+
+#define dolog(...) fprintf (stderr, "dma: " __VA_ARGS__)
+#ifdef DEBUG_DMA
+#define lwarn(...) fprintf (stderr, "dma: " __VA_ARGS__)
+#define linfo(...) fprintf (stderr, "dma: " __VA_ARGS__)
+#define ldebug(...) fprintf (stderr, "dma: " __VA_ARGS__)
+#else
+#define lwarn(...)
+#define linfo(...)
+#define ldebug(...)
+#endif
+
+#define LENOFA(a) ((int) (sizeof(a)/sizeof(a[0])))
+
+struct dma_regs {
+ int now[2];
+ uint16_t base[2];
+ uint8_t mode;
+ uint8_t page;
+ uint8_t pageh;
+ uint8_t dack;
+ uint8_t eop;
+ DMA_transfer_handler transfer_handler;
+ void *opaque;
+};
+
+#define ADDR 0
+#define COUNT 1
+
+static struct dma_cont {
+ uint8_t status;
+ uint8_t command;
+ uint8_t mask;
+ uint8_t flip_flop;
+ int dshift;
+ struct dma_regs regs[4];
+} dma_controllers[2];
+
+enum {
+ CMD_MEMORY_TO_MEMORY = 0x01,
+ CMD_FIXED_ADDRESS = 0x02,
+ CMD_BLOCK_CONTROLLER = 0x04,
+ CMD_COMPRESSED_TIME = 0x08,
+ CMD_CYCLIC_PRIORITY = 0x10,
+ CMD_EXTENDED_WRITE = 0x20,
+ CMD_LOW_DREQ = 0x40,
+ CMD_LOW_DACK = 0x80,
+ CMD_NOT_SUPPORTED = CMD_MEMORY_TO_MEMORY | CMD_FIXED_ADDRESS
+ | CMD_COMPRESSED_TIME | CMD_CYCLIC_PRIORITY | CMD_EXTENDED_WRITE
+ | CMD_LOW_DREQ | CMD_LOW_DACK
+
+};
+
+static int channels[8] = {-1, 2, 3, 1, -1, -1, -1, 0};
+
+static void write_page (void *opaque, uint32_t nport, uint32_t data)
+{
+ struct dma_cont *d = opaque;
+ int ichan;
+
+ ichan = channels[nport & 7];
+ if (-1 == ichan) {
+ dolog ("invalid channel %#x %#x\n", nport, data);
+ return;
+ }
+ d->regs[ichan].page = data;
+}
+
+static void write_pageh (void *opaque, uint32_t nport, uint32_t data)
+{
+ struct dma_cont *d = opaque;
+ int ichan;
+
+ ichan = channels[nport & 7];
+ if (-1 == ichan) {
+ dolog ("invalid channel %#x %#x\n", nport, data);
+ return;
+ }
+ d->regs[ichan].pageh = data;
+}
+
+static uint32_t read_page (void *opaque, uint32_t nport)
+{
+ struct dma_cont *d = opaque;
+ int ichan;
+
+ ichan = channels[nport & 7];
+ if (-1 == ichan) {
+ dolog ("invalid channel read %#x\n", nport);
+ return 0;
+ }
+ return d->regs[ichan].page;
+}
+
+static uint32_t read_pageh (void *opaque, uint32_t nport)
+{
+ struct dma_cont *d = opaque;
+ int ichan;
+
+ ichan = channels[nport & 7];
+ if (-1 == ichan) {
+ dolog ("invalid channel read %#x\n", nport);
+ return 0;
+ }
+ return d->regs[ichan].pageh;
+}
+
+static inline void init_chan (struct dma_cont *d, int ichan)
+{
+ struct dma_regs *r;
+
+ r = d->regs + ichan;
+ r->now[ADDR] = r->base[ADDR] << d->dshift;
+ r->now[COUNT] = 0;
+}
+
+static inline int getff (struct dma_cont *d)
+{
+ int ff;
+
+ ff = d->flip_flop;
+ d->flip_flop = !ff;
+ return ff;
+}
+
+static uint32_t read_chan (void *opaque, uint32_t nport)
+{
+ struct dma_cont *d = opaque;
+ int ichan, nreg, iport, ff, val, dir;
+ struct dma_regs *r;
+
+ iport = (nport >> d->dshift) & 0x0f;
+ ichan = iport >> 1;
+ nreg = iport & 1;
+ r = d->regs + ichan;
+
+ dir = ((r->mode >> 5) & 1) ? -1 : 1;
+ ff = getff (d);
+ if (nreg)
+ val = (r->base[COUNT] << d->dshift) - r->now[COUNT];
+ else
+ val = r->now[ADDR] + r->now[COUNT] * dir;
+
+ ldebug ("read_chan %#x -> %d\n", iport, val);
+ return (val >> (d->dshift + (ff << 3))) & 0xff;
+}
+
+static void write_chan (void *opaque, uint32_t nport, uint32_t data)
+{
+ struct dma_cont *d = opaque;
+ int iport, ichan, nreg;
+ struct dma_regs *r;
+
+ iport = (nport >> d->dshift) & 0x0f;
+ ichan = iport >> 1;
+ nreg = iport & 1;
+ r = d->regs + ichan;
+ if (getff (d)) {
+ r->base[nreg] = (r->base[nreg] & 0xff) | ((data << 8) & 0xff00);
+ init_chan (d, ichan);
+ } else {
+ r->base[nreg] = (r->base[nreg] & 0xff00) | (data & 0xff);
+ }
+}
+
+static void write_cont (void *opaque, uint32_t nport, uint32_t data)
+{
+ struct dma_cont *d = opaque;
+ int iport, ichan = 0;
+
+ iport = (nport >> d->dshift) & 0x0f;
+ switch (iport) {
+ case 0x08: /* command */
+ if ((data != 0) && (data & CMD_NOT_SUPPORTED)) {
+ dolog ("command %#x not supported\n", data);
+ return;
+ }
+ d->command = data;
+ break;
+
+ case 0x09:
+ ichan = data & 3;
+ if (data & 4) {
+ d->status |= 1 << (ichan + 4);
+ }
+ else {
+ d->status &= ~(1 << (ichan + 4));
+ }
+ d->status &= ~(1 << ichan);
+ break;
+
+ case 0x0a: /* single mask */
+ if (data & 4)
+ d->mask |= 1 << (data & 3);
+ else
+ d->mask &= ~(1 << (data & 3));
+ break;
+
+ case 0x0b: /* mode */
+ {
+ ichan = data & 3;
+#ifdef DEBUG_DMA
+ {
+ int op, ai, dir, opmode;
+ op = (data >> 2) & 3;
+ ai = (data >> 4) & 1;
+ dir = (data >> 5) & 1;
+ opmode = (data >> 6) & 3;
+
+ linfo ("ichan %d, op %d, ai %d, dir %d, opmode %d\n",
+ ichan, op, ai, dir, opmode);
+ }
+#endif
+ d->regs[ichan].mode = data;
+ break;
+ }
+
+ case 0x0c: /* clear flip flop */
+ d->flip_flop = 0;
+ break;
+
+ case 0x0d: /* reset */
+ d->flip_flop = 0;
+ d->mask = ~0;
+ d->status = 0;
+ d->command = 0;
+ break;
+
+ case 0x0e: /* clear mask for all channels */
+ d->mask = 0;
+ break;
+
+ case 0x0f: /* write mask for all channels */
+ d->mask = data;
+ break;
+
+ default:
+ dolog ("unknown iport %#x\n", iport);
+ break;
+ }
+
+#ifdef DEBUG_DMA
+ if (0xc != iport) {
+ linfo ("write_cont: nport %#06x, ichan % 2d, val %#06x\n",
+ nport, ichan, data);
+ }
+#endif
+}
+
+static uint32_t read_cont (void *opaque, uint32_t nport)
+{
+ struct dma_cont *d = opaque;
+ int iport, val;
+
+ iport = (nport >> d->dshift) & 0x0f;
+ switch (iport) {
+ case 0x08: /* status */
+ val = d->status;
+ d->status &= 0xf0;
+ break;
+ case 0x0f: /* mask */
+ val = d->mask;
+ break;
+ default:
+ val = 0;
+ break;
+ }
+
+ ldebug ("read_cont: nport %#06x, iport %#04x val %#x\n", nport, iport, val);
+ return val;
+}
+
+int DMA_get_channel_mode (int nchan)
+{
+ return dma_controllers[nchan > 3].regs[nchan & 3].mode;
+}
+
+void DMA_hold_DREQ (int nchan)
+{
+ int ncont, ichan;
+
+ ncont = nchan > 3;
+ ichan = nchan & 3;
+ linfo ("held cont=%d chan=%d\n", ncont, ichan);
+ dma_controllers[ncont].status |= 1 << (ichan + 4);
+}
+
+void DMA_release_DREQ (int nchan)
+{
+ int ncont, ichan;
+
+ ncont = nchan > 3;
+ ichan = nchan & 3;
+ linfo ("released cont=%d chan=%d\n", ncont, ichan);
+ dma_controllers[ncont].status &= ~(1 << (ichan + 4));
+}
+
+static void channel_run (int ncont, int ichan)
+{
+ int n;
+ struct dma_regs *r = &dma_controllers[ncont].regs[ichan];
+#ifdef DEBUG_DMA
+ int dir, opmode;
+
+ dir = (r->mode >> 5) & 1;
+ opmode = (r->mode >> 6) & 3;
+
+ if (dir) {
+ dolog ("DMA in address decrement mode\n");
+ }
+ if (opmode != 1) {
+ dolog ("DMA not in single mode select %#x\n", opmode);
+ }
+#endif
+
+ r = dma_controllers[ncont].regs + ichan;
+ n = r->transfer_handler (r->opaque, ichan + (ncont << 2),
+ r->now[COUNT], (r->base[COUNT] + 1) << ncont);
+ r->now[COUNT] = n;
+ ldebug ("dma_pos %d size %d\n", n, (r->base[COUNT] + 1) << ncont);
+}
+
+void DMA_run (void)
+{
+ struct dma_cont *d;
+ int icont, ichan;
+
+ d = dma_controllers;
+
+ for (icont = 0; icont < 2; icont++, d++) {
+ for (ichan = 0; ichan < 4; ichan++) {
+ int mask;
+
+ mask = 1 << ichan;
+
+ if ((0 == (d->mask & mask)) && (0 != (d->status & (mask << 4))))
+ channel_run (icont, ichan);
+ }
+ }
+}
+
+void DMA_register_channel (int nchan,
+ DMA_transfer_handler transfer_handler,
+ void *opaque)
+{
+ struct dma_regs *r;
+ int ichan, ncont;
+
+ ncont = nchan > 3;
+ ichan = nchan & 3;
+
+ r = dma_controllers[ncont].regs + ichan;
+ r->transfer_handler = transfer_handler;
+ r->opaque = opaque;
+}
+
+int DMA_read_memory (int nchan, void *buf, int pos, int len)
+{
+ struct dma_regs *r = &dma_controllers[nchan > 3].regs[nchan & 3];
+ target_ulong addr = ((r->pageh & 0x7f) << 24) | (r->page << 16) | r->now[ADDR];
+
+ if (r->mode & 0x20) {
+ int i;
+ uint8_t *p = buf;
+
+ cpu_physical_memory_read (addr - pos - len, buf, len);
+ /* What about 16bit transfers? */
+ for (i = 0; i < len >> 1; i++) {
+ uint8_t b = p[len - i - 1];
+ p[i] = b;
+ }
+ }
+ else
+ cpu_physical_memory_read (addr + pos, buf, len);
+
+ return len;
+}
+
+int DMA_write_memory (int nchan, void *buf, int pos, int len)
+{
+ struct dma_regs *r = &dma_controllers[nchan > 3].regs[nchan & 3];
+ target_ulong addr = ((r->pageh & 0x7f) << 24) | (r->page << 16) | r->now[ADDR];
+
+ if (r->mode & 0x20) {
+ int i;
+ uint8_t *p = buf;
+
+ cpu_physical_memory_write (addr - pos - len, buf, len);
+ /* What about 16bit transfers? */
+ for (i = 0; i < len; i++) {
+ uint8_t b = p[len - i - 1];
+ p[i] = b;
+ }
+ }
+ else
+ cpu_physical_memory_write (addr + pos, buf, len);
+
+ return len;
+}
+
+/* request the emulator to transfer a new DMA memory block ASAP */
+void DMA_schedule(int nchan)
+{
+ cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT);
+}
+
+static void dma_reset(void *opaque)
+{
+ struct dma_cont *d = opaque;
+ write_cont (d, (0x0d << d->dshift), 0);
+}
+
+/* dshift = 0: 8 bit DMA, 1 = 16 bit DMA */
+static void dma_init2(struct dma_cont *d, int base, int dshift,
+ int page_base, int pageh_base)
+{
+ const static int page_port_list[] = { 0x1, 0x2, 0x3, 0x7 };
+ int i;
+
+ d->dshift = dshift;
+ for (i = 0; i < 8; i++) {
+ register_ioport_write (base + (i << dshift), 1, 1, write_chan, d);
+ register_ioport_read (base + (i << dshift), 1, 1, read_chan, d);
+ }
+ for (i = 0; i < LENOFA (page_port_list); i++) {
+ register_ioport_write (page_base + page_port_list[i], 1, 1,
+ write_page, d);
+ register_ioport_read (page_base + page_port_list[i], 1, 1,
+ read_page, d);
+ if (pageh_base >= 0) {
+ register_ioport_write (pageh_base + page_port_list[i], 1, 1,
+ write_pageh, d);
+ register_ioport_read (pageh_base + page_port_list[i], 1, 1,
+ read_pageh, d);
+ }
+ }
+ for (i = 0; i < 8; i++) {
+ register_ioport_write (base + ((i + 8) << dshift), 1, 1,
+ write_cont, d);
+ register_ioport_read (base + ((i + 8) << dshift), 1, 1,
+ read_cont, d);
+ }
+ qemu_register_reset(dma_reset, d);
+ dma_reset(d);
+}
+
+static void dma_save (QEMUFile *f, void *opaque)
+{
+ struct dma_cont *d = opaque;
+ int i;
+
+ /* qemu_put_8s (f, &d->status); */
+ qemu_put_8s (f, &d->command);
+ qemu_put_8s (f, &d->mask);
+ qemu_put_8s (f, &d->flip_flop);
+ qemu_put_be32s (f, &d->dshift);
+
+ for (i = 0; i < 4; ++i) {
+ struct dma_regs *r = &d->regs[i];
+ qemu_put_be32s (f, &r->now[0]);
+ qemu_put_be32s (f, &r->now[1]);
+ qemu_put_be16s (f, &r->base[0]);
+ qemu_put_be16s (f, &r->base[1]);
+ qemu_put_8s (f, &r->mode);
+ qemu_put_8s (f, &r->page);
+ qemu_put_8s (f, &r->pageh);
+ qemu_put_8s (f, &r->dack);
+ qemu_put_8s (f, &r->eop);
+ }
+}
+
+static int dma_load (QEMUFile *f, void *opaque, int version_id)
+{
+ struct dma_cont *d = opaque;
+ int i;
+
+ if (version_id != 1)
+ return -EINVAL;
+
+ /* qemu_get_8s (f, &d->status); */
+ qemu_get_8s (f, &d->command);
+ qemu_get_8s (f, &d->mask);
+ qemu_get_8s (f, &d->flip_flop);
+ qemu_get_be32s (f, &d->dshift);
+
+ for (i = 0; i < 4; ++i) {
+ struct dma_regs *r = &d->regs[i];
+ qemu_get_be32s (f, &r->now[0]);
+ qemu_get_be32s (f, &r->now[1]);
+ qemu_get_be16s (f, &r->base[0]);
+ qemu_get_be16s (f, &r->base[1]);
+ qemu_get_8s (f, &r->mode);
+ qemu_get_8s (f, &r->page);
+ qemu_get_8s (f, &r->pageh);
+ qemu_get_8s (f, &r->dack);
+ qemu_get_8s (f, &r->eop);
+ }
+ return 0;
+}
+
+void DMA_init (int high_page_enable)
+{
+ dma_init2(&dma_controllers[0], 0x00, 0, 0x80,
+ high_page_enable ? 0x480 : -1);
+ dma_init2(&dma_controllers[1], 0xc0, 1, 0x88,
+ high_page_enable ? 0x488 : -1);
+ register_savevm ("dma", 0, 1, dma_save, dma_load, &dma_controllers[0]);
+ register_savevm ("dma", 1, 1, dma_save, dma_load, &dma_controllers[1]);
+}
--- /dev/null
+/*
+ * QEMU Floppy disk emulator (Intel 82078)
+ *
+ * Copyright (c) 2003 Jocelyn Mayer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+
+/********************************************************/
+/* debug Floppy devices */
+//#define DEBUG_FLOPPY
+
+#ifdef DEBUG_FLOPPY
+#define FLOPPY_DPRINTF(fmt, args...) \
+do { printf("FLOPPY: " fmt , ##args); } while (0)
+#else
+#define FLOPPY_DPRINTF(fmt, args...)
+#endif
+
+#define FLOPPY_ERROR(fmt, args...) \
+do { printf("FLOPPY ERROR: %s: " fmt, __func__ , ##args); } while (0)
+
+/********************************************************/
+/* Floppy drive emulation */
+
+/* Will always be a fixed parameter for us */
+#define FD_SECTOR_LEN 512
+#define FD_SECTOR_SC 2 /* Sector size code */
+
+/* Floppy disk drive emulation */
+typedef enum fdisk_type_t {
+ FDRIVE_DISK_288 = 0x01, /* 2.88 MB disk */
+ FDRIVE_DISK_144 = 0x02, /* 1.44 MB disk */
+ FDRIVE_DISK_720 = 0x03, /* 720 kB disk */
+ FDRIVE_DISK_USER = 0x04, /* User defined geometry */
+ FDRIVE_DISK_NONE = 0x05, /* No disk */
+} fdisk_type_t;
+
+typedef enum fdrive_type_t {
+ FDRIVE_DRV_144 = 0x00, /* 1.44 MB 3"5 drive */
+ FDRIVE_DRV_288 = 0x01, /* 2.88 MB 3"5 drive */
+ FDRIVE_DRV_120 = 0x02, /* 1.2 MB 5"25 drive */
+ FDRIVE_DRV_NONE = 0x03, /* No drive connected */
+} fdrive_type_t;
+
+typedef enum fdrive_flags_t {
+ FDRIVE_MOTOR_ON = 0x01, /* motor on/off */
+ FDRIVE_REVALIDATE = 0x02, /* Revalidated */
+} fdrive_flags_t;
+
+typedef enum fdisk_flags_t {
+ FDISK_DBL_SIDES = 0x01,
+} fdisk_flags_t;
+
+typedef struct fdrive_t {
+ BlockDriverState *bs;
+ /* Drive status */
+ fdrive_type_t drive;
+ fdrive_flags_t drflags;
+ uint8_t perpendicular; /* 2.88 MB access mode */
+ /* Position */
+ uint8_t head;
+ uint8_t track;
+ uint8_t sect;
+ /* Last operation status */
+ uint8_t dir; /* Direction */
+ uint8_t rw; /* Read/write */
+ /* Media */
+ fdisk_flags_t flags;
+ uint8_t last_sect; /* Nb sector per track */
+ uint8_t max_track; /* Nb of tracks */
+ uint16_t bps; /* Bytes per sector */
+ uint8_t ro; /* Is read-only */
+} fdrive_t;
+
+static void fd_init (fdrive_t *drv, BlockDriverState *bs)
+{
+ /* Drive */
+ drv->bs = bs;
+ drv->drive = FDRIVE_DRV_NONE;
+ drv->drflags = 0;
+ drv->perpendicular = 0;
+ /* Disk */
+ drv->last_sect = 0;
+ drv->max_track = 0;
+}
+
+static int _fd_sector (uint8_t head, uint8_t track,
+ uint8_t sect, uint8_t last_sect)
+{
+ return (((track * 2) + head) * last_sect) + sect - 1;
+}
+
+/* Returns current position, in sectors, for given drive */
+static int fd_sector (fdrive_t *drv)
+{
+ return _fd_sector(drv->head, drv->track, drv->sect, drv->last_sect);
+}
+
+static int fd_seek (fdrive_t *drv, uint8_t head, uint8_t track, uint8_t sect,
+ int enable_seek)
+{
+ uint32_t sector;
+ int ret;
+
+ if (track > drv->max_track ||
+ (head != 0 && (drv->flags & FDISK_DBL_SIDES) == 0)) {
+ FLOPPY_DPRINTF("try to read %d %02x %02x (max=%d %d %02x %02x)\n",
+ head, track, sect, 1,
+ (drv->flags & FDISK_DBL_SIDES) == 0 ? 0 : 1,
+ drv->max_track, drv->last_sect);
+ return 2;
+ }
+ if (sect > drv->last_sect) {
+ FLOPPY_DPRINTF("try to read %d %02x %02x (max=%d %d %02x %02x)\n",
+ head, track, sect, 1,
+ (drv->flags & FDISK_DBL_SIDES) == 0 ? 0 : 1,
+ drv->max_track, drv->last_sect);
+ return 3;
+ }
+ sector = _fd_sector(head, track, sect, drv->last_sect);
+ ret = 0;
+ if (sector != fd_sector(drv)) {
+#if 0
+ if (!enable_seek) {
+ FLOPPY_ERROR("no implicit seek %d %02x %02x (max=%d %02x %02x)\n",
+ head, track, sect, 1, drv->max_track, drv->last_sect);
+ return 4;
+ }
+#endif
+ drv->head = head;
+ if (drv->track != track)
+ ret = 1;
+ drv->track = track;
+ drv->sect = sect;
+ }
+
+ return ret;
+}
+
+/* Set drive back to track 0 */
+static void fd_recalibrate (fdrive_t *drv)
+{
+ FLOPPY_DPRINTF("recalibrate\n");
+ drv->head = 0;
+ drv->track = 0;
+ drv->sect = 1;
+ drv->dir = 1;
+ drv->rw = 0;
+}
+
+/* Recognize floppy formats */
+typedef struct fd_format_t {
+ fdrive_type_t drive;
+ fdisk_type_t disk;
+ uint8_t last_sect;
+ uint8_t max_track;
+ uint8_t max_head;
+ const unsigned char *str;
+} fd_format_t;
+
+static fd_format_t fd_formats[] = {
+ /* First entry is default format */
+ /* 1.44 MB 3"1/2 floppy disks */
+ { FDRIVE_DRV_144, FDRIVE_DISK_144, 18, 80, 1, "1.44 MB 3\"1/2", },
+ { FDRIVE_DRV_144, FDRIVE_DISK_144, 20, 80, 1, "1.6 MB 3\"1/2", },
+ { FDRIVE_DRV_144, FDRIVE_DISK_144, 21, 80, 1, "1.68 MB 3\"1/2", },
+ { FDRIVE_DRV_144, FDRIVE_DISK_144, 21, 82, 1, "1.72 MB 3\"1/2", },
+ { FDRIVE_DRV_144, FDRIVE_DISK_144, 21, 83, 1, "1.74 MB 3\"1/2", },
+ { FDRIVE_DRV_144, FDRIVE_DISK_144, 22, 80, 1, "1.76 MB 3\"1/2", },
+ { FDRIVE_DRV_144, FDRIVE_DISK_144, 23, 80, 1, "1.84 MB 3\"1/2", },
+ { FDRIVE_DRV_144, FDRIVE_DISK_144, 24, 80, 1, "1.92 MB 3\"1/2", },
+ /* 2.88 MB 3"1/2 floppy disks */
+ { FDRIVE_DRV_288, FDRIVE_DISK_288, 36, 80, 1, "2.88 MB 3\"1/2", },
+ { FDRIVE_DRV_288, FDRIVE_DISK_288, 39, 80, 1, "3.12 MB 3\"1/2", },
+ { FDRIVE_DRV_288, FDRIVE_DISK_288, 40, 80, 1, "3.2 MB 3\"1/2", },
+ { FDRIVE_DRV_288, FDRIVE_DISK_288, 44, 80, 1, "3.52 MB 3\"1/2", },
+ { FDRIVE_DRV_288, FDRIVE_DISK_288, 48, 80, 1, "3.84 MB 3\"1/2", },
+ /* 720 kB 3"1/2 floppy disks */
+ { FDRIVE_DRV_144, FDRIVE_DISK_720, 9, 80, 1, "720 kB 3\"1/2", },
+ { FDRIVE_DRV_144, FDRIVE_DISK_720, 10, 80, 1, "800 kB 3\"1/2", },
+ { FDRIVE_DRV_144, FDRIVE_DISK_720, 10, 82, 1, "820 kB 3\"1/2", },
+ { FDRIVE_DRV_144, FDRIVE_DISK_720, 10, 83, 1, "830 kB 3\"1/2", },
+ { FDRIVE_DRV_144, FDRIVE_DISK_720, 13, 80, 1, "1.04 MB 3\"1/2", },
+ { FDRIVE_DRV_144, FDRIVE_DISK_720, 14, 80, 1, "1.12 MB 3\"1/2", },
+ /* 1.2 MB 5"1/4 floppy disks */
+ { FDRIVE_DRV_120, FDRIVE_DISK_288, 15, 80, 1, "1.2 kB 5\"1/4", },
+ { FDRIVE_DRV_120, FDRIVE_DISK_288, 18, 80, 1, "1.44 MB 5\"1/4", },
+ { FDRIVE_DRV_120, FDRIVE_DISK_288, 18, 82, 1, "1.48 MB 5\"1/4", },
+ { FDRIVE_DRV_120, FDRIVE_DISK_288, 18, 83, 1, "1.49 MB 5\"1/4", },
+ { FDRIVE_DRV_120, FDRIVE_DISK_288, 20, 80, 1, "1.6 MB 5\"1/4", },
+ /* 720 kB 5"1/4 floppy disks */
+ { FDRIVE_DRV_120, FDRIVE_DISK_288, 9, 80, 1, "720 kB 5\"1/4", },
+ { FDRIVE_DRV_120, FDRIVE_DISK_288, 11, 80, 1, "880 kB 5\"1/4", },
+ /* 360 kB 5"1/4 floppy disks */
+ { FDRIVE_DRV_120, FDRIVE_DISK_288, 9, 40, 1, "360 kB 5\"1/4", },
+ { FDRIVE_DRV_120, FDRIVE_DISK_288, 9, 40, 0, "180 kB 5\"1/4", },
+ { FDRIVE_DRV_120, FDRIVE_DISK_288, 10, 41, 1, "410 kB 5\"1/4", },
+ { FDRIVE_DRV_120, FDRIVE_DISK_288, 10, 42, 1, "420 kB 5\"1/4", },
+ /* 320 kB 5"1/4 floppy disks */
+ { FDRIVE_DRV_120, FDRIVE_DISK_288, 8, 40, 1, "320 kB 5\"1/4", },
+ { FDRIVE_DRV_120, FDRIVE_DISK_288, 8, 40, 0, "160 kB 5\"1/4", },
+ /* 360 kB must match 5"1/4 better than 3"1/2... */
+ { FDRIVE_DRV_144, FDRIVE_DISK_720, 9, 80, 0, "360 kB 3\"1/2", },
+ /* end */
+ { FDRIVE_DRV_NONE, FDRIVE_DISK_NONE, -1, -1, 0, NULL, },
+};
+
+/* Revalidate a disk drive after a disk change */
+static void fd_revalidate (fdrive_t *drv)
+{
+ fd_format_t *parse;
+ int64_t nb_sectors, size;
+ int i, first_match, match;
+ int nb_heads, max_track, last_sect, ro;
+
+ FLOPPY_DPRINTF("revalidate\n");
+ drv->drflags &= ~FDRIVE_REVALIDATE;
+ if (drv->bs != NULL && bdrv_is_inserted(drv->bs)) {
+ ro = bdrv_is_read_only(drv->bs);
+ bdrv_get_geometry_hint(drv->bs, &nb_heads, &max_track, &last_sect);
+ if (nb_heads != 0 && max_track != 0 && last_sect != 0) {
+ FLOPPY_DPRINTF("User defined disk (%d %d %d)",
+ nb_heads - 1, max_track, last_sect);
+ } else {
+ bdrv_get_geometry(drv->bs, &nb_sectors);
+ match = -1;
+ first_match = -1;
+ for (i = 0;; i++) {
+ parse = &fd_formats[i];
+ if (parse->drive == FDRIVE_DRV_NONE)
+ break;
+ if (drv->drive == parse->drive ||
+ drv->drive == FDRIVE_DRV_NONE) {
+ size = (parse->max_head + 1) * parse->max_track *
+ parse->last_sect;
+ if (nb_sectors == size) {
+ match = i;
+ break;
+ }
+ if (first_match == -1)
+ first_match = i;
+ }
+ }
+ if (match == -1) {
+ if (first_match == -1)
+ match = 1;
+ else
+ match = first_match;
+ parse = &fd_formats[match];
+ }
+ nb_heads = parse->max_head + 1;
+ max_track = parse->max_track;
+ last_sect = parse->last_sect;
+ drv->drive = parse->drive;
+ FLOPPY_DPRINTF("%s floppy disk (%d h %d t %d s) %s\n", parse->str,
+ nb_heads, max_track, last_sect, ro ? "ro" : "rw");
+ }
+ if (nb_heads == 1) {
+ drv->flags &= ~FDISK_DBL_SIDES;
+ } else {
+ drv->flags |= FDISK_DBL_SIDES;
+ }
+ drv->max_track = max_track;
+ drv->last_sect = last_sect;
+ drv->ro = ro;
+ } else {
+ FLOPPY_DPRINTF("No disk in drive\n");
+ drv->last_sect = 0;
+ drv->max_track = 0;
+ drv->flags &= ~FDISK_DBL_SIDES;
+ }
+ drv->drflags |= FDRIVE_REVALIDATE;
+}
+
+/* Motor control */
+static void fd_start (fdrive_t *drv)
+{
+ drv->drflags |= FDRIVE_MOTOR_ON;
+}
+
+static void fd_stop (fdrive_t *drv)
+{
+ drv->drflags &= ~FDRIVE_MOTOR_ON;
+}
+
+/* Re-initialise a drives (motor off, repositioned) */
+static void fd_reset (fdrive_t *drv)
+{
+ fd_stop(drv);
+ fd_recalibrate(drv);
+}
+
+/********************************************************/
+/* Intel 82078 floppy disk controller emulation */
+
+static void fdctrl_reset (fdctrl_t *fdctrl, int do_irq);
+static void fdctrl_reset_fifo (fdctrl_t *fdctrl);
+static int fdctrl_transfer_handler (void *opaque, int nchan,
+ int dma_pos, int dma_len);
+static void fdctrl_raise_irq (fdctrl_t *fdctrl, uint8_t status);
+static void fdctrl_result_timer(void *opaque);
+
+static uint32_t fdctrl_read_statusB (fdctrl_t *fdctrl);
+static uint32_t fdctrl_read_dor (fdctrl_t *fdctrl);
+static void fdctrl_write_dor (fdctrl_t *fdctrl, uint32_t value);
+static uint32_t fdctrl_read_tape (fdctrl_t *fdctrl);
+static void fdctrl_write_tape (fdctrl_t *fdctrl, uint32_t value);
+static uint32_t fdctrl_read_main_status (fdctrl_t *fdctrl);
+static void fdctrl_write_rate (fdctrl_t *fdctrl, uint32_t value);
+static uint32_t fdctrl_read_data (fdctrl_t *fdctrl);
+static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value);
+static uint32_t fdctrl_read_dir (fdctrl_t *fdctrl);
+
+enum {
+ FD_CTRL_ACTIVE = 0x01, /* XXX: suppress that */
+ FD_CTRL_RESET = 0x02,
+ FD_CTRL_SLEEP = 0x04, /* XXX: suppress that */
+ FD_CTRL_BUSY = 0x08, /* dma transfer in progress */
+ FD_CTRL_INTR = 0x10,
+};
+
+enum {
+ FD_DIR_WRITE = 0,
+ FD_DIR_READ = 1,
+ FD_DIR_SCANE = 2,
+ FD_DIR_SCANL = 3,
+ FD_DIR_SCANH = 4,
+};
+
+enum {
+ FD_STATE_CMD = 0x00,
+ FD_STATE_STATUS = 0x01,
+ FD_STATE_DATA = 0x02,
+ FD_STATE_STATE = 0x03,
+ FD_STATE_MULTI = 0x10,
+ FD_STATE_SEEK = 0x20,
+ FD_STATE_FORMAT = 0x40,
+};
+
+#define FD_STATE(state) ((state) & FD_STATE_STATE)
+#define FD_SET_STATE(state, new_state) \
+do { (state) = ((state) & ~FD_STATE_STATE) | (new_state); } while (0)
+#define FD_MULTI_TRACK(state) ((state) & FD_STATE_MULTI)
+#define FD_DID_SEEK(state) ((state) & FD_STATE_SEEK)
+#define FD_FORMAT_CMD(state) ((state) & FD_STATE_FORMAT)
+
+struct fdctrl_t {
+ fdctrl_t *fdctrl;
+ /* Controller's identification */
+ uint8_t version;
+ /* HW */
+ int irq_lvl;
+ int dma_chann;
+ uint32_t io_base;
+ /* Controller state */
+ QEMUTimer *result_timer;
+ uint8_t state;
+ uint8_t dma_en;
+ uint8_t cur_drv;
+ uint8_t bootsel;
+ /* Command FIFO */
+ uint8_t fifo[FD_SECTOR_LEN];
+ uint32_t data_pos;
+ uint32_t data_len;
+ uint8_t data_state;
+ uint8_t data_dir;
+ uint8_t int_status;
+ uint8_t eot; /* last wanted sector */
+ /* States kept only to be returned back */
+ /* Timers state */
+ uint8_t timer0;
+ uint8_t timer1;
+ /* precompensation */
+ uint8_t precomp_trk;
+ uint8_t config;
+ uint8_t lock;
+ /* Power down config (also with status regB access mode */
+ uint8_t pwrd;
+ /* Floppy drives */
+ fdrive_t drives[2];
+};
+
+static uint32_t fdctrl_read (void *opaque, uint32_t reg)
+{
+ fdctrl_t *fdctrl = opaque;
+ uint32_t retval;
+
+ switch (reg & 0x07) {
+ case 0x01:
+ retval = fdctrl_read_statusB(fdctrl);
+ break;
+ case 0x02:
+ retval = fdctrl_read_dor(fdctrl);
+ break;
+ case 0x03:
+ retval = fdctrl_read_tape(fdctrl);
+ break;
+ case 0x04:
+ retval = fdctrl_read_main_status(fdctrl);
+ break;
+ case 0x05:
+ retval = fdctrl_read_data(fdctrl);
+ break;
+ case 0x07:
+ retval = fdctrl_read_dir(fdctrl);
+ break;
+ default:
+ retval = (uint32_t)(-1);
+ break;
+ }
+ FLOPPY_DPRINTF("read reg%d: 0x%02x\n", reg & 7, retval);
+
+ return retval;
+}
+
+static void fdctrl_write (void *opaque, uint32_t reg, uint32_t value)
+{
+ fdctrl_t *fdctrl = opaque;
+
+ FLOPPY_DPRINTF("write reg%d: 0x%02x\n", reg & 7, value);
+
+ switch (reg & 0x07) {
+ case 0x02:
+ fdctrl_write_dor(fdctrl, value);
+ break;
+ case 0x03:
+ fdctrl_write_tape(fdctrl, value);
+ break;
+ case 0x04:
+ fdctrl_write_rate(fdctrl, value);
+ break;
+ case 0x05:
+ fdctrl_write_data(fdctrl, value);
+ break;
+ default:
+ break;
+ }
+}
+
+static void fd_change_cb (void *opaque)
+{
+ fdrive_t *drv = opaque;
+
+ FLOPPY_DPRINTF("disk change\n");
+ fd_revalidate(drv);
+#if 0
+ fd_recalibrate(drv);
+ fdctrl_reset_fifo(drv->fdctrl);
+ fdctrl_raise_irq(drv->fdctrl, 0x20);
+#endif
+}
+
+fdctrl_t *fdctrl_init (int irq_lvl, int dma_chann, int mem_mapped,
+ uint32_t io_base,
+ BlockDriverState **fds)
+{
+ fdctrl_t *fdctrl;
+// int io_mem;
+ int i;
+
+ FLOPPY_DPRINTF("init controller\n");
+ fdctrl = qemu_mallocz(sizeof(fdctrl_t));
+ if (!fdctrl)
+ return NULL;
+ fdctrl->result_timer = qemu_new_timer(vm_clock,
+ fdctrl_result_timer, fdctrl);
+
+ fdctrl->version = 0x90; /* Intel 82078 controller */
+ fdctrl->irq_lvl = irq_lvl;
+ fdctrl->dma_chann = dma_chann;
+ fdctrl->io_base = io_base;
+ fdctrl->config = 0x60; /* Implicit seek, polling & FIFO enabled */
+ if (fdctrl->dma_chann != -1) {
+ fdctrl->dma_en = 1;
+ DMA_register_channel(dma_chann, &fdctrl_transfer_handler, fdctrl);
+ } else {
+ fdctrl->dma_en = 0;
+ }
+ for (i = 0; i < 2; i++) {
+ fd_init(&fdctrl->drives[i], fds[i]);
+ if (fds[i]) {
+ bdrv_set_change_cb(fds[i],
+ &fd_change_cb, &fdctrl->drives[i]);
+ }
+ }
+ fdctrl_reset(fdctrl, 0);
+ fdctrl->state = FD_CTRL_ACTIVE;
+ if (mem_mapped) {
+ FLOPPY_ERROR("memory mapped floppy not supported by now !\n");
+#if 0
+ io_mem = cpu_register_io_memory(0, fdctrl_mem_read, fdctrl_mem_write);
+ cpu_register_physical_memory(base, 0x08, io_mem);
+#endif
+ } else {
+ register_ioport_read(io_base + 0x01, 5, 1, &fdctrl_read, fdctrl);
+ register_ioport_read(io_base + 0x07, 1, 1, &fdctrl_read, fdctrl);
+ register_ioport_write(io_base + 0x01, 5, 1, &fdctrl_write, fdctrl);
+ register_ioport_write(io_base + 0x07, 1, 1, &fdctrl_write, fdctrl);
+ }
+ for (i = 0; i < 2; i++) {
+ fd_revalidate(&fdctrl->drives[i]);
+ }
+
+ return fdctrl;
+}
+
+/* XXX: may change if moved to bdrv */
+int fdctrl_get_drive_type(fdctrl_t *fdctrl, int drive_num)
+{
+ return fdctrl->drives[drive_num].drive;
+}
+
+/* Change IRQ state */
+static void fdctrl_reset_irq (fdctrl_t *fdctrl)
+{
+ FLOPPY_DPRINTF("Reset interrupt\n");
+ pic_set_irq(fdctrl->irq_lvl, 0);
+ fdctrl->state &= ~FD_CTRL_INTR;
+}
+
+static void fdctrl_raise_irq (fdctrl_t *fdctrl, uint8_t status)
+{
+ if (~(fdctrl->state & FD_CTRL_INTR)) {
+ pic_set_irq(fdctrl->irq_lvl, 1);
+ fdctrl->state |= FD_CTRL_INTR;
+ }
+ FLOPPY_DPRINTF("Set interrupt status to 0x%02x\n", status);
+ fdctrl->int_status = status;
+}
+
+/* Reset controller */
+static void fdctrl_reset (fdctrl_t *fdctrl, int do_irq)
+{
+ int i;
+
+ FLOPPY_DPRINTF("reset controller\n");
+ fdctrl_reset_irq(fdctrl);
+ /* Initialise controller */
+ fdctrl->cur_drv = 0;
+ /* FIFO state */
+ fdctrl->data_pos = 0;
+ fdctrl->data_len = 0;
+ fdctrl->data_state = FD_STATE_CMD;
+ fdctrl->data_dir = FD_DIR_WRITE;
+ for (i = 0; i < MAX_FD; i++)
+ fd_reset(&fdctrl->drives[i]);
+ fdctrl_reset_fifo(fdctrl);
+ if (do_irq)
+ fdctrl_raise_irq(fdctrl, 0xc0);
+}
+
+static inline fdrive_t *drv0 (fdctrl_t *fdctrl)
+{
+ return &fdctrl->drives[fdctrl->bootsel];
+}
+
+static inline fdrive_t *drv1 (fdctrl_t *fdctrl)
+{
+ return &fdctrl->drives[1 - fdctrl->bootsel];
+}
+
+static fdrive_t *get_cur_drv (fdctrl_t *fdctrl)
+{
+ return fdctrl->cur_drv == 0 ? drv0(fdctrl) : drv1(fdctrl);
+}
+
+/* Status B register : 0x01 (read-only) */
+static uint32_t fdctrl_read_statusB (fdctrl_t *fdctrl)
+{
+ FLOPPY_DPRINTF("status register: 0x00\n");
+ return 0;
+}
+
+/* Digital output register : 0x02 */
+static uint32_t fdctrl_read_dor (fdctrl_t *fdctrl)
+{
+ uint32_t retval = 0;
+
+ /* Drive motors state indicators */
+ if (drv0(fdctrl)->drflags & FDRIVE_MOTOR_ON)
+ retval |= 1 << 5;
+ if (drv1(fdctrl)->drflags & FDRIVE_MOTOR_ON)
+ retval |= 1 << 4;
+ /* DMA enable */
+ retval |= fdctrl->dma_en << 3;
+ /* Reset indicator */
+ retval |= (fdctrl->state & FD_CTRL_RESET) == 0 ? 0x04 : 0;
+ /* Selected drive */
+ retval |= fdctrl->cur_drv;
+ FLOPPY_DPRINTF("digital output register: 0x%02x\n", retval);
+
+ return retval;
+}
+
+static void fdctrl_write_dor (fdctrl_t *fdctrl, uint32_t value)
+{
+ /* Reset mode */
+ if (fdctrl->state & FD_CTRL_RESET) {
+ if (!(value & 0x04)) {
+ FLOPPY_DPRINTF("Floppy controller in RESET state !\n");
+ return;
+ }
+ }
+ FLOPPY_DPRINTF("digital output register set to 0x%02x\n", value);
+ /* Drive motors state indicators */
+ if (value & 0x20)
+ fd_start(drv1(fdctrl));
+ else
+ fd_stop(drv1(fdctrl));
+ if (value & 0x10)
+ fd_start(drv0(fdctrl));
+ else
+ fd_stop(drv0(fdctrl));
+ /* DMA enable */
+#if 0
+ if (fdctrl->dma_chann != -1)
+ fdctrl->dma_en = 1 - ((value >> 3) & 1);
+#endif
+ /* Reset */
+ if (!(value & 0x04)) {
+ if (!(fdctrl->state & FD_CTRL_RESET)) {
+ FLOPPY_DPRINTF("controller enter RESET state\n");
+ fdctrl->state |= FD_CTRL_RESET;
+ }
+ } else {
+ if (fdctrl->state & FD_CTRL_RESET) {
+ FLOPPY_DPRINTF("controller out of RESET state\n");
+ fdctrl_reset(fdctrl, 1);
+ fdctrl->state &= ~(FD_CTRL_RESET | FD_CTRL_SLEEP);
+ }
+ }
+ /* Selected drive */
+ fdctrl->cur_drv = value & 1;
+}
+
+/* Tape drive register : 0x03 */
+static uint32_t fdctrl_read_tape (fdctrl_t *fdctrl)
+{
+ uint32_t retval = 0;
+
+ /* Disk boot selection indicator */
+ retval |= fdctrl->bootsel << 2;
+ /* Tape indicators: never allowed */
+ FLOPPY_DPRINTF("tape drive register: 0x%02x\n", retval);
+
+ return retval;
+}
+
+static void fdctrl_write_tape (fdctrl_t *fdctrl, uint32_t value)
+{
+ /* Reset mode */
+ if (fdctrl->state & FD_CTRL_RESET) {
+ FLOPPY_DPRINTF("Floppy controller in RESET state !\n");
+ return;
+ }
+ FLOPPY_DPRINTF("tape drive register set to 0x%02x\n", value);
+ /* Disk boot selection indicator */
+ fdctrl->bootsel = (value >> 2) & 1;
+ /* Tape indicators: never allow */
+}
+
+/* Main status register : 0x04 (read) */
+static uint32_t fdctrl_read_main_status (fdctrl_t *fdctrl)
+{
+ uint32_t retval = 0;
+
+ fdctrl->state &= ~(FD_CTRL_SLEEP | FD_CTRL_RESET);
+ if (!(fdctrl->state & FD_CTRL_BUSY)) {
+ /* Data transfer allowed */
+ retval |= 0x80;
+ /* Data transfer direction indicator */
+ if (fdctrl->data_dir == FD_DIR_READ)
+ retval |= 0x40;
+ }
+ /* Should handle 0x20 for SPECIFY command */
+ /* Command busy indicator */
+ if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA ||
+ FD_STATE(fdctrl->data_state) == FD_STATE_STATUS)
+ retval |= 0x10;
+ FLOPPY_DPRINTF("main status register: 0x%02x\n", retval);
+
+ return retval;
+}
+
+/* Data select rate register : 0x04 (write) */
+static void fdctrl_write_rate (fdctrl_t *fdctrl, uint32_t value)
+{
+ /* Reset mode */
+ if (fdctrl->state & FD_CTRL_RESET) {
+ FLOPPY_DPRINTF("Floppy controller in RESET state !\n");
+ return;
+ }
+ FLOPPY_DPRINTF("select rate register set to 0x%02x\n", value);
+ /* Reset: autoclear */
+ if (value & 0x80) {
+ fdctrl->state |= FD_CTRL_RESET;
+ fdctrl_reset(fdctrl, 1);
+ fdctrl->state &= ~FD_CTRL_RESET;
+ }
+ if (value & 0x40) {
+ fdctrl->state |= FD_CTRL_SLEEP;
+ fdctrl_reset(fdctrl, 1);
+ }
+// fdctrl.precomp = (value >> 2) & 0x07;
+}
+
+/* Digital input register : 0x07 (read-only) */
+static uint32_t fdctrl_read_dir (fdctrl_t *fdctrl)
+{
+ uint32_t retval = 0;
+
+ if (drv0(fdctrl)->drflags & FDRIVE_REVALIDATE ||
+ drv1(fdctrl)->drflags & FDRIVE_REVALIDATE)
+ retval |= 0x80;
+ if (retval != 0)
+ FLOPPY_DPRINTF("Floppy digital input register: 0x%02x\n", retval);
+ drv0(fdctrl)->drflags &= ~FDRIVE_REVALIDATE;
+ drv1(fdctrl)->drflags &= ~FDRIVE_REVALIDATE;
+
+ return retval;
+}
+
+/* FIFO state control */
+static void fdctrl_reset_fifo (fdctrl_t *fdctrl)
+{
+ fdctrl->data_dir = FD_DIR_WRITE;
+ fdctrl->data_pos = 0;
+ FD_SET_STATE(fdctrl->data_state, FD_STATE_CMD);
+}
+
+/* Set FIFO status for the host to read */
+static void fdctrl_set_fifo (fdctrl_t *fdctrl, int fifo_len, int do_irq)
+{
+ fdctrl->data_dir = FD_DIR_READ;
+ fdctrl->data_len = fifo_len;
+ fdctrl->data_pos = 0;
+ FD_SET_STATE(fdctrl->data_state, FD_STATE_STATUS);
+ if (do_irq)
+ fdctrl_raise_irq(fdctrl, 0x00);
+}
+
+/* Set an error: unimplemented/unknown command */
+static void fdctrl_unimplemented (fdctrl_t *fdctrl)
+{
+#if 0
+ fdrive_t *cur_drv;
+
+ cur_drv = get_cur_drv(fdctrl);
+ fdctrl->fifo[0] = 0x60 | (cur_drv->head << 2) | fdctrl->cur_drv;
+ fdctrl->fifo[1] = 0x00;
+ fdctrl->fifo[2] = 0x00;
+ fdctrl_set_fifo(fdctrl, 3, 1);
+#else
+ // fdctrl_reset_fifo(fdctrl);
+ fdctrl->fifo[0] = 0x80;
+ fdctrl_set_fifo(fdctrl, 1, 0);
+#endif
+}
+
+/* Callback for transfer end (stop or abort) */
+static void fdctrl_stop_transfer (fdctrl_t *fdctrl, uint8_t status0,
+ uint8_t status1, uint8_t status2)
+{
+ fdrive_t *cur_drv;
+
+ cur_drv = get_cur_drv(fdctrl);
+ FLOPPY_DPRINTF("transfer status: %02x %02x %02x (%02x)\n",
+ status0, status1, status2,
+ status0 | (cur_drv->head << 2) | fdctrl->cur_drv);
+ fdctrl->fifo[0] = status0 | (cur_drv->head << 2) | fdctrl->cur_drv;
+ fdctrl->fifo[1] = status1;
+ fdctrl->fifo[2] = status2;
+ fdctrl->fifo[3] = cur_drv->track;
+ fdctrl->fifo[4] = cur_drv->head;
+ fdctrl->fifo[5] = cur_drv->sect;
+ fdctrl->fifo[6] = FD_SECTOR_SC;
+ fdctrl->data_dir = FD_DIR_READ;
+ if (fdctrl->state & FD_CTRL_BUSY) {
+ DMA_release_DREQ(fdctrl->dma_chann);
+ fdctrl->state &= ~FD_CTRL_BUSY;
+ }
+ fdctrl_set_fifo(fdctrl, 7, 1);
+}
+
+/* Prepare a data transfer (either DMA or FIFO) */
+static void fdctrl_start_transfer (fdctrl_t *fdctrl, int direction)
+{
+ fdrive_t *cur_drv;
+ uint8_t kh, kt, ks;
+ int did_seek;
+
+ fdctrl->cur_drv = fdctrl->fifo[1] & 1;
+ cur_drv = get_cur_drv(fdctrl);
+ kt = fdctrl->fifo[2];
+ kh = fdctrl->fifo[3];
+ ks = fdctrl->fifo[4];
+ FLOPPY_DPRINTF("Start transfer at %d %d %02x %02x (%d)\n",
+ fdctrl->cur_drv, kh, kt, ks,
+ _fd_sector(kh, kt, ks, cur_drv->last_sect));
+ did_seek = 0;
+ switch (fd_seek(cur_drv, kh, kt, ks, fdctrl->config & 0x40)) {
+ case 2:
+ /* sect too big */
+ fdctrl_stop_transfer(fdctrl, 0x40, 0x00, 0x00);
+ fdctrl->fifo[3] = kt;
+ fdctrl->fifo[4] = kh;
+ fdctrl->fifo[5] = ks;
+ return;
+ case 3:
+ /* track too big */
+ fdctrl_stop_transfer(fdctrl, 0x40, 0x80, 0x00);
+ fdctrl->fifo[3] = kt;
+ fdctrl->fifo[4] = kh;
+ fdctrl->fifo[5] = ks;
+ return;
+ case 4:
+ /* No seek enabled */
+ fdctrl_stop_transfer(fdctrl, 0x40, 0x00, 0x00);
+ fdctrl->fifo[3] = kt;
+ fdctrl->fifo[4] = kh;
+ fdctrl->fifo[5] = ks;
+ return;
+ case 1:
+ did_seek = 1;
+ break;
+ default:
+ break;
+ }
+ /* Set the FIFO state */
+ fdctrl->data_dir = direction;
+ fdctrl->data_pos = 0;
+ FD_SET_STATE(fdctrl->data_state, FD_STATE_DATA); /* FIFO ready for data */
+ if (fdctrl->fifo[0] & 0x80)
+ fdctrl->data_state |= FD_STATE_MULTI;
+ else
+ fdctrl->data_state &= ~FD_STATE_MULTI;
+ if (did_seek)
+ fdctrl->data_state |= FD_STATE_SEEK;
+ else
+ fdctrl->data_state &= ~FD_STATE_SEEK;
+ if (fdctrl->fifo[5] == 00) {
+ fdctrl->data_len = fdctrl->fifo[8];
+ } else {
+ int tmp;
+ fdctrl->data_len = 128 << fdctrl->fifo[5];
+ tmp = (cur_drv->last_sect - ks + 1);
+ if (fdctrl->fifo[0] & 0x80)
+ tmp += cur_drv->last_sect;
+ fdctrl->data_len *= tmp;
+ }
+ fdctrl->eot = fdctrl->fifo[6];
+ if (fdctrl->dma_en) {
+ int dma_mode;
+ /* DMA transfer are enabled. Check if DMA channel is well programmed */
+ dma_mode = DMA_get_channel_mode(fdctrl->dma_chann);
+ dma_mode = (dma_mode >> 2) & 3;
+ FLOPPY_DPRINTF("dma_mode=%d direction=%d (%d - %d)\n",
+ dma_mode, direction,
+ (128 << fdctrl->fifo[5]) *
+ (cur_drv->last_sect - ks + 1), fdctrl->data_len);
+ if (((direction == FD_DIR_SCANE || direction == FD_DIR_SCANL ||
+ direction == FD_DIR_SCANH) && dma_mode == 0) ||
+ (direction == FD_DIR_WRITE && dma_mode == 2) ||
+ (direction == FD_DIR_READ && dma_mode == 1)) {
+ /* No access is allowed until DMA transfer has completed */
+ fdctrl->state |= FD_CTRL_BUSY;
+ /* Now, we just have to wait for the DMA controller to
+ * recall us...
+ */
+ DMA_hold_DREQ(fdctrl->dma_chann);
+ DMA_schedule(fdctrl->dma_chann);
+ return;
+ } else {
+ FLOPPY_ERROR("dma_mode=%d direction=%d\n", dma_mode, direction);
+ }
+ }
+ FLOPPY_DPRINTF("start non-DMA transfer\n");
+ /* IO based transfer: calculate len */
+ fdctrl_raise_irq(fdctrl, 0x00);
+
+ return;
+}
+
+/* Prepare a transfer of deleted data */
+static void fdctrl_start_transfer_del (fdctrl_t *fdctrl, int direction)
+{
+ /* We don't handle deleted data,
+ * so we don't return *ANYTHING*
+ */
+ fdctrl_stop_transfer(fdctrl, 0x60, 0x00, 0x00);
+}
+
+/* handlers for DMA transfers */
+static int fdctrl_transfer_handler (void *opaque, int nchan,
+ int dma_pos, int dma_len)
+{
+ fdctrl_t *fdctrl;
+ fdrive_t *cur_drv;
+ int len, start_pos, rel_pos;
+ uint8_t status0 = 0x00, status1 = 0x00, status2 = 0x00;
+
+ fdctrl = opaque;
+ if (!(fdctrl->state & FD_CTRL_BUSY)) {
+ FLOPPY_DPRINTF("Not in DMA transfer mode !\n");
+ return 0;
+ }
+ cur_drv = get_cur_drv(fdctrl);
+ if (fdctrl->data_dir == FD_DIR_SCANE || fdctrl->data_dir == FD_DIR_SCANL ||
+ fdctrl->data_dir == FD_DIR_SCANH)
+ status2 = 0x04;
+ if (dma_len > fdctrl->data_len)
+ dma_len = fdctrl->data_len;
+ if (cur_drv->bs == NULL) {
+ if (fdctrl->data_dir == FD_DIR_WRITE)
+ fdctrl_stop_transfer(fdctrl, 0x60, 0x00, 0x00);
+ else
+ fdctrl_stop_transfer(fdctrl, 0x40, 0x00, 0x00);
+ len = 0;
+ goto transfer_error;
+ }
+ rel_pos = fdctrl->data_pos % FD_SECTOR_LEN;
+ for (start_pos = fdctrl->data_pos; fdctrl->data_pos < dma_len;) {
+ len = dma_len - fdctrl->data_pos;
+ if (len + rel_pos > FD_SECTOR_LEN)
+ len = FD_SECTOR_LEN - rel_pos;
+ FLOPPY_DPRINTF("copy %d bytes (%d %d %d) %d pos %d %02x %02x "
+ "(%d-0x%08x 0x%08x)\n", len, size, fdctrl->data_pos,
+ fdctrl->data_len, fdctrl->cur_drv, cur_drv->head,
+ cur_drv->track, cur_drv->sect, fd_sector(cur_drv),
+ fd_sector(cur_drv) * 512, addr);
+ if (fdctrl->data_dir != FD_DIR_WRITE ||
+ len < FD_SECTOR_LEN || rel_pos != 0) {
+ /* READ & SCAN commands and realign to a sector for WRITE */
+ if (bdrv_read(cur_drv->bs, fd_sector(cur_drv),
+ fdctrl->fifo, 1) < 0) {
+ FLOPPY_DPRINTF("Floppy: error getting sector %d\n",
+ fd_sector(cur_drv));
+ /* Sure, image size is too small... */
+ memset(fdctrl->fifo, 0, FD_SECTOR_LEN);
+ }
+ }
+ switch (fdctrl->data_dir) {
+ case FD_DIR_READ:
+ /* READ commands */
+ DMA_write_memory (nchan, fdctrl->fifo + rel_pos,
+ fdctrl->data_pos, len);
+/* cpu_physical_memory_write(addr + fdctrl->data_pos, */
+/* fdctrl->fifo + rel_pos, len); */
+ break;
+ case FD_DIR_WRITE:
+ /* WRITE commands */
+ DMA_read_memory (nchan, fdctrl->fifo + rel_pos,
+ fdctrl->data_pos, len);
+/* cpu_physical_memory_read(addr + fdctrl->data_pos, */
+/* fdctrl->fifo + rel_pos, len); */
+ if (bdrv_write(cur_drv->bs, fd_sector(cur_drv),
+ fdctrl->fifo, 1) < 0) {
+ FLOPPY_ERROR("writting sector %d\n", fd_sector(cur_drv));
+ fdctrl_stop_transfer(fdctrl, 0x60, 0x00, 0x00);
+ goto transfer_error;
+ }
+ break;
+ default:
+ /* SCAN commands */
+ {
+ uint8_t tmpbuf[FD_SECTOR_LEN];
+ int ret;
+ DMA_read_memory (nchan, tmpbuf, fdctrl->data_pos, len);
+/* cpu_physical_memory_read(addr + fdctrl->data_pos, */
+/* tmpbuf, len); */
+ ret = memcmp(tmpbuf, fdctrl->fifo + rel_pos, len);
+ if (ret == 0) {
+ status2 = 0x08;
+ goto end_transfer;
+ }
+ if ((ret < 0 && fdctrl->data_dir == FD_DIR_SCANL) ||
+ (ret > 0 && fdctrl->data_dir == FD_DIR_SCANH)) {
+ status2 = 0x00;
+ goto end_transfer;
+ }
+ }
+ break;
+ }
+ fdctrl->data_pos += len;
+ rel_pos = fdctrl->data_pos % FD_SECTOR_LEN;
+ if (rel_pos == 0) {
+ /* Seek to next sector */
+ FLOPPY_DPRINTF("seek to next sector (%d %02x %02x => %d) (%d)\n",
+ cur_drv->head, cur_drv->track, cur_drv->sect,
+ fd_sector(cur_drv),
+ fdctrl->data_pos - size);
+ /* XXX: cur_drv->sect >= cur_drv->last_sect should be an
+ error in fact */
+ if (cur_drv->sect >= cur_drv->last_sect ||
+ cur_drv->sect == fdctrl->eot) {
+ cur_drv->sect = 1;
+ if (FD_MULTI_TRACK(fdctrl->data_state)) {
+ if (cur_drv->head == 0 &&
+ (cur_drv->flags & FDISK_DBL_SIDES) != 0) {
+ cur_drv->head = 1;
+ } else {
+ cur_drv->head = 0;
+ cur_drv->track++;
+ if ((cur_drv->flags & FDISK_DBL_SIDES) == 0)
+ break;
+ }
+ } else {
+ cur_drv->track++;
+ break;
+ }
+ FLOPPY_DPRINTF("seek to next track (%d %02x %02x => %d)\n",
+ cur_drv->head, cur_drv->track,
+ cur_drv->sect, fd_sector(cur_drv));
+ } else {
+ cur_drv->sect++;
+ }
+ }
+ }
+end_transfer:
+ len = fdctrl->data_pos - start_pos;
+ FLOPPY_DPRINTF("end transfer %d %d %d\n",
+ fdctrl->data_pos, len, fdctrl->data_len);
+ if (fdctrl->data_dir == FD_DIR_SCANE ||
+ fdctrl->data_dir == FD_DIR_SCANL ||
+ fdctrl->data_dir == FD_DIR_SCANH)
+ status2 = 0x08;
+ if (FD_DID_SEEK(fdctrl->data_state))
+ status0 |= 0x20;
+ fdctrl->data_len -= len;
+ // if (fdctrl->data_len == 0)
+ fdctrl_stop_transfer(fdctrl, status0, status1, status2);
+transfer_error:
+
+ return len;
+}
+
+/* Data register : 0x05 */
+static uint32_t fdctrl_read_data (fdctrl_t *fdctrl)
+{
+ fdrive_t *cur_drv;
+ uint32_t retval = 0;
+ int pos, len;
+
+ cur_drv = get_cur_drv(fdctrl);
+ fdctrl->state &= ~FD_CTRL_SLEEP;
+ if (FD_STATE(fdctrl->data_state) == FD_STATE_CMD) {
+ FLOPPY_ERROR("can't read data in CMD state\n");
+ return 0;
+ }
+ pos = fdctrl->data_pos;
+ if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA) {
+ pos %= FD_SECTOR_LEN;
+ if (pos == 0) {
+ len = fdctrl->data_len - fdctrl->data_pos;
+ if (len > FD_SECTOR_LEN)
+ len = FD_SECTOR_LEN;
+ bdrv_read(cur_drv->bs, fd_sector(cur_drv),
+ fdctrl->fifo, len);
+ }
+ }
+ retval = fdctrl->fifo[pos];
+ if (++fdctrl->data_pos == fdctrl->data_len) {
+ fdctrl->data_pos = 0;
+ /* Switch from transfer mode to status mode
+ * then from status mode to command mode
+ */
+ if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA) {
+ fdctrl_stop_transfer(fdctrl, 0x20, 0x00, 0x00);
+ } else {
+ fdctrl_reset_fifo(fdctrl);
+ fdctrl_reset_irq(fdctrl);
+ }
+ }
+ FLOPPY_DPRINTF("data register: 0x%02x\n", retval);
+
+ return retval;
+}
+
+static void fdctrl_format_sector (fdctrl_t *fdctrl)
+{
+ fdrive_t *cur_drv;
+ uint8_t kh, kt, ks;
+ int did_seek;
+
+ fdctrl->cur_drv = fdctrl->fifo[1] & 1;
+ cur_drv = get_cur_drv(fdctrl);
+ kt = fdctrl->fifo[6];
+ kh = fdctrl->fifo[7];
+ ks = fdctrl->fifo[8];
+ FLOPPY_DPRINTF("format sector at %d %d %02x %02x (%d)\n",
+ fdctrl->cur_drv, kh, kt, ks,
+ _fd_sector(kh, kt, ks, cur_drv->last_sect));
+ did_seek = 0;
+ switch (fd_seek(cur_drv, kh, kt, ks, fdctrl->config & 0x40)) {
+ case 2:
+ /* sect too big */
+ fdctrl_stop_transfer(fdctrl, 0x40, 0x00, 0x00);
+ fdctrl->fifo[3] = kt;
+ fdctrl->fifo[4] = kh;
+ fdctrl->fifo[5] = ks;
+ return;
+ case 3:
+ /* track too big */
+ fdctrl_stop_transfer(fdctrl, 0x40, 0x80, 0x00);
+ fdctrl->fifo[3] = kt;
+ fdctrl->fifo[4] = kh;
+ fdctrl->fifo[5] = ks;
+ return;
+ case 4:
+ /* No seek enabled */
+ fdctrl_stop_transfer(fdctrl, 0x40, 0x00, 0x00);
+ fdctrl->fifo[3] = kt;
+ fdctrl->fifo[4] = kh;
+ fdctrl->fifo[5] = ks;
+ return;
+ case 1:
+ did_seek = 1;
+ fdctrl->data_state |= FD_STATE_SEEK;
+ break;
+ default:
+ break;
+ }
+ memset(fdctrl->fifo, 0, FD_SECTOR_LEN);
+ if (cur_drv->bs == NULL ||
+ bdrv_write(cur_drv->bs, fd_sector(cur_drv), fdctrl->fifo, 1) < 0) {
+ FLOPPY_ERROR("formating sector %d\n", fd_sector(cur_drv));
+ fdctrl_stop_transfer(fdctrl, 0x60, 0x00, 0x00);
+ } else {
+ if (cur_drv->sect == cur_drv->last_sect) {
+ fdctrl->data_state &= ~FD_STATE_FORMAT;
+ /* Last sector done */
+ if (FD_DID_SEEK(fdctrl->data_state))
+ fdctrl_stop_transfer(fdctrl, 0x20, 0x00, 0x00);
+ else
+ fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
+ } else {
+ /* More to do */
+ fdctrl->data_pos = 0;
+ fdctrl->data_len = 4;
+ }
+ }
+}
+
+static void fdctrl_write_data (fdctrl_t *fdctrl, uint32_t value)
+{
+ fdrive_t *cur_drv;
+
+ cur_drv = get_cur_drv(fdctrl);
+ /* Reset mode */
+ if (fdctrl->state & FD_CTRL_RESET) {
+ FLOPPY_DPRINTF("Floppy controller in RESET state !\n");
+ return;
+ }
+ fdctrl->state &= ~FD_CTRL_SLEEP;
+ if (FD_STATE(fdctrl->data_state) == FD_STATE_STATUS) {
+ FLOPPY_ERROR("can't write data in status mode\n");
+ return;
+ }
+ /* Is it write command time ? */
+ if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA) {
+ /* FIFO data write */
+ fdctrl->fifo[fdctrl->data_pos++] = value;
+ if (fdctrl->data_pos % FD_SECTOR_LEN == (FD_SECTOR_LEN - 1) ||
+ fdctrl->data_pos == fdctrl->data_len) {
+ bdrv_write(cur_drv->bs, fd_sector(cur_drv),
+ fdctrl->fifo, FD_SECTOR_LEN);
+ }
+ /* Switch from transfer mode to status mode
+ * then from status mode to command mode
+ */
+ if (FD_STATE(fdctrl->data_state) == FD_STATE_DATA)
+ fdctrl_stop_transfer(fdctrl, 0x20, 0x00, 0x00);
+ return;
+ }
+ if (fdctrl->data_pos == 0) {
+ /* Command */
+ switch (value & 0x5F) {
+ case 0x46:
+ /* READ variants */
+ FLOPPY_DPRINTF("READ command\n");
+ /* 8 parameters cmd */
+ fdctrl->data_len = 9;
+ goto enqueue;
+ case 0x4C:
+ /* READ_DELETED variants */
+ FLOPPY_DPRINTF("READ_DELETED command\n");
+ /* 8 parameters cmd */
+ fdctrl->data_len = 9;
+ goto enqueue;
+ case 0x50:
+ /* SCAN_EQUAL variants */
+ FLOPPY_DPRINTF("SCAN_EQUAL command\n");
+ /* 8 parameters cmd */
+ fdctrl->data_len = 9;
+ goto enqueue;
+ case 0x56:
+ /* VERIFY variants */
+ FLOPPY_DPRINTF("VERIFY command\n");
+ /* 8 parameters cmd */
+ fdctrl->data_len = 9;
+ goto enqueue;
+ case 0x59:
+ /* SCAN_LOW_OR_EQUAL variants */
+ FLOPPY_DPRINTF("SCAN_LOW_OR_EQUAL command\n");
+ /* 8 parameters cmd */
+ fdctrl->data_len = 9;
+ goto enqueue;
+ case 0x5D:
+ /* SCAN_HIGH_OR_EQUAL variants */
+ FLOPPY_DPRINTF("SCAN_HIGH_OR_EQUAL command\n");
+ /* 8 parameters cmd */
+ fdctrl->data_len = 9;
+ goto enqueue;
+ default:
+ break;
+ }
+ switch (value & 0x7F) {
+ case 0x45:
+ /* WRITE variants */
+ FLOPPY_DPRINTF("WRITE command\n");
+ /* 8 parameters cmd */
+ fdctrl->data_len = 9;
+ goto enqueue;
+ case 0x49:
+ /* WRITE_DELETED variants */
+ FLOPPY_DPRINTF("WRITE_DELETED command\n");
+ /* 8 parameters cmd */
+ fdctrl->data_len = 9;
+ goto enqueue;
+ default:
+ break;
+ }
+ switch (value) {
+ case 0x03:
+ /* SPECIFY */
+ FLOPPY_DPRINTF("SPECIFY command\n");
+ /* 1 parameter cmd */
+ fdctrl->data_len = 3;
+ goto enqueue;
+ case 0x04:
+ /* SENSE_DRIVE_STATUS */
+ FLOPPY_DPRINTF("SENSE_DRIVE_STATUS command\n");
+ /* 1 parameter cmd */
+ fdctrl->data_len = 2;
+ goto enqueue;
+ case 0x07:
+ /* RECALIBRATE */
+ FLOPPY_DPRINTF("RECALIBRATE command\n");
+ /* 1 parameter cmd */
+ fdctrl->data_len = 2;
+ goto enqueue;
+ case 0x08:
+ /* SENSE_INTERRUPT_STATUS */
+ FLOPPY_DPRINTF("SENSE_INTERRUPT_STATUS command (%02x)\n",
+ fdctrl->int_status);
+ /* No parameters cmd: returns status if no interrupt */
+#if 0
+ fdctrl->fifo[0] =
+ fdctrl->int_status | (cur_drv->head << 2) | fdctrl->cur_drv;
+#else
+ /* XXX: int_status handling is broken for read/write
+ commands, so we do this hack. It should be suppressed
+ ASAP */
+ fdctrl->fifo[0] =
+ 0x20 | (cur_drv->head << 2) | fdctrl->cur_drv;
+#endif
+ fdctrl->fifo[1] = cur_drv->track;
+ fdctrl_set_fifo(fdctrl, 2, 0);
+ fdctrl_reset_irq(fdctrl);
+ fdctrl->int_status = 0xC0;
+ return;
+ case 0x0E:
+ /* DUMPREG */
+ FLOPPY_DPRINTF("DUMPREG command\n");
+ /* Drives position */
+ fdctrl->fifo[0] = drv0(fdctrl)->track;
+ fdctrl->fifo[1] = drv1(fdctrl)->track;
+ fdctrl->fifo[2] = 0;
+ fdctrl->fifo[3] = 0;
+ /* timers */
+ fdctrl->fifo[4] = fdctrl->timer0;
+ fdctrl->fifo[5] = (fdctrl->timer1 << 1) | fdctrl->dma_en;
+ fdctrl->fifo[6] = cur_drv->last_sect;
+ fdctrl->fifo[7] = (fdctrl->lock << 7) |
+ (cur_drv->perpendicular << 2);
+ fdctrl->fifo[8] = fdctrl->config;
+ fdctrl->fifo[9] = fdctrl->precomp_trk;
+ fdctrl_set_fifo(fdctrl, 10, 0);
+ return;
+ case 0x0F:
+ /* SEEK */
+ FLOPPY_DPRINTF("SEEK command\n");
+ /* 2 parameters cmd */
+ fdctrl->data_len = 3;
+ goto enqueue;
+ case 0x10:
+ /* VERSION */
+ FLOPPY_DPRINTF("VERSION command\n");
+ /* No parameters cmd */
+ /* Controller's version */
+ fdctrl->fifo[0] = fdctrl->version;
+ fdctrl_set_fifo(fdctrl, 1, 1);
+ return;
+ case 0x12:
+ /* PERPENDICULAR_MODE */
+ FLOPPY_DPRINTF("PERPENDICULAR_MODE command\n");
+ /* 1 parameter cmd */
+ fdctrl->data_len = 2;
+ goto enqueue;
+ case 0x13:
+ /* CONFIGURE */
+ FLOPPY_DPRINTF("CONFIGURE command\n");
+ /* 3 parameters cmd */
+ fdctrl->data_len = 4;
+ goto enqueue;
+ case 0x14:
+ /* UNLOCK */
+ FLOPPY_DPRINTF("UNLOCK command\n");
+ /* No parameters cmd */
+ fdctrl->lock = 0;
+ fdctrl->fifo[0] = 0;
+ fdctrl_set_fifo(fdctrl, 1, 0);
+ return;
+ case 0x17:
+ /* POWERDOWN_MODE */
+ FLOPPY_DPRINTF("POWERDOWN_MODE command\n");
+ /* 2 parameters cmd */
+ fdctrl->data_len = 3;
+ goto enqueue;
+ case 0x18:
+ /* PART_ID */
+ FLOPPY_DPRINTF("PART_ID command\n");
+ /* No parameters cmd */
+ fdctrl->fifo[0] = 0x41; /* Stepping 1 */
+ fdctrl_set_fifo(fdctrl, 1, 0);
+ return;
+ case 0x2C:
+ /* SAVE */
+ FLOPPY_DPRINTF("SAVE command\n");
+ /* No parameters cmd */
+ fdctrl->fifo[0] = 0;
+ fdctrl->fifo[1] = 0;
+ /* Drives position */
+ fdctrl->fifo[2] = drv0(fdctrl)->track;
+ fdctrl->fifo[3] = drv1(fdctrl)->track;
+ fdctrl->fifo[4] = 0;
+ fdctrl->fifo[5] = 0;
+ /* timers */
+ fdctrl->fifo[6] = fdctrl->timer0;
+ fdctrl->fifo[7] = fdctrl->timer1;
+ fdctrl->fifo[8] = cur_drv->last_sect;
+ fdctrl->fifo[9] = (fdctrl->lock << 7) |
+ (cur_drv->perpendicular << 2);
+ fdctrl->fifo[10] = fdctrl->config;
+ fdctrl->fifo[11] = fdctrl->precomp_trk;
+ fdctrl->fifo[12] = fdctrl->pwrd;
+ fdctrl->fifo[13] = 0;
+ fdctrl->fifo[14] = 0;
+ fdctrl_set_fifo(fdctrl, 15, 1);
+ return;
+ case 0x33:
+ /* OPTION */
+ FLOPPY_DPRINTF("OPTION command\n");
+ /* 1 parameter cmd */
+ fdctrl->data_len = 2;
+ goto enqueue;
+ case 0x42:
+ /* READ_TRACK */
+ FLOPPY_DPRINTF("READ_TRACK command\n");
+ /* 8 parameters cmd */
+ fdctrl->data_len = 9;
+ goto enqueue;
+ case 0x4A:
+ /* READ_ID */
+ FLOPPY_DPRINTF("READ_ID command\n");
+ /* 1 parameter cmd */
+ fdctrl->data_len = 2;
+ goto enqueue;
+ case 0x4C:
+ /* RESTORE */
+ FLOPPY_DPRINTF("RESTORE command\n");
+ /* 17 parameters cmd */
+ fdctrl->data_len = 18;
+ goto enqueue;
+ case 0x4D:
+ /* FORMAT_TRACK */
+ FLOPPY_DPRINTF("FORMAT_TRACK command\n");
+ /* 5 parameters cmd */
+ fdctrl->data_len = 6;
+ goto enqueue;
+ case 0x8E:
+ /* DRIVE_SPECIFICATION_COMMAND */
+ FLOPPY_DPRINTF("DRIVE_SPECIFICATION_COMMAND command\n");
+ /* 5 parameters cmd */
+ fdctrl->data_len = 6;
+ goto enqueue;
+ case 0x8F:
+ /* RELATIVE_SEEK_OUT */
+ FLOPPY_DPRINTF("RELATIVE_SEEK_OUT command\n");
+ /* 2 parameters cmd */
+ fdctrl->data_len = 3;
+ goto enqueue;
+ case 0x94:
+ /* LOCK */
+ FLOPPY_DPRINTF("LOCK command\n");
+ /* No parameters cmd */
+ fdctrl->lock = 1;
+ fdctrl->fifo[0] = 0x10;
+ fdctrl_set_fifo(fdctrl, 1, 1);
+ return;
+ case 0xCD:
+ /* FORMAT_AND_WRITE */
+ FLOPPY_DPRINTF("FORMAT_AND_WRITE command\n");
+ /* 10 parameters cmd */
+ fdctrl->data_len = 11;
+ goto enqueue;
+ case 0xCF:
+ /* RELATIVE_SEEK_IN */
+ FLOPPY_DPRINTF("RELATIVE_SEEK_IN command\n");
+ /* 2 parameters cmd */
+ fdctrl->data_len = 3;
+ goto enqueue;
+ default:
+ /* Unknown command */
+ FLOPPY_ERROR("unknown command: 0x%02x\n", value);
+ fdctrl_unimplemented(fdctrl);
+ return;
+ }
+ }
+enqueue:
+ FLOPPY_DPRINTF("%s: %02x\n", __func__, value);
+ fdctrl->fifo[fdctrl->data_pos] = value;
+ if (++fdctrl->data_pos == fdctrl->data_len) {
+ /* We now have all parameters
+ * and will be able to treat the command
+ */
+ if (fdctrl->data_state & FD_STATE_FORMAT) {
+ fdctrl_format_sector(fdctrl);
+ return;
+ }
+ switch (fdctrl->fifo[0] & 0x1F) {
+ case 0x06:
+ {
+ /* READ variants */
+ FLOPPY_DPRINTF("treat READ command\n");
+ fdctrl_start_transfer(fdctrl, FD_DIR_READ);
+ return;
+ }
+ case 0x0C:
+ /* READ_DELETED variants */
+// FLOPPY_DPRINTF("treat READ_DELETED command\n");
+ FLOPPY_ERROR("treat READ_DELETED command\n");
+ fdctrl_start_transfer_del(fdctrl, FD_DIR_READ);
+ return;
+ case 0x16:
+ /* VERIFY variants */
+// FLOPPY_DPRINTF("treat VERIFY command\n");
+ FLOPPY_ERROR("treat VERIFY command\n");
+ fdctrl_stop_transfer(fdctrl, 0x20, 0x00, 0x00);
+ return;
+ case 0x10:
+ /* SCAN_EQUAL variants */
+// FLOPPY_DPRINTF("treat SCAN_EQUAL command\n");
+ FLOPPY_ERROR("treat SCAN_EQUAL command\n");
+ fdctrl_start_transfer(fdctrl, FD_DIR_SCANE);
+ return;
+ case 0x19:
+ /* SCAN_LOW_OR_EQUAL variants */
+// FLOPPY_DPRINTF("treat SCAN_LOW_OR_EQUAL command\n");
+ FLOPPY_ERROR("treat SCAN_LOW_OR_EQUAL command\n");
+ fdctrl_start_transfer(fdctrl, FD_DIR_SCANL);
+ return;
+ case 0x1D:
+ /* SCAN_HIGH_OR_EQUAL variants */
+// FLOPPY_DPRINTF("treat SCAN_HIGH_OR_EQUAL command\n");
+ FLOPPY_ERROR("treat SCAN_HIGH_OR_EQUAL command\n");
+ fdctrl_start_transfer(fdctrl, FD_DIR_SCANH);
+ return;
+ default:
+ break;
+ }
+ switch (fdctrl->fifo[0] & 0x3F) {
+ case 0x05:
+ /* WRITE variants */
+ FLOPPY_DPRINTF("treat WRITE command (%02x)\n", fdctrl->fifo[0]);
+ fdctrl_start_transfer(fdctrl, FD_DIR_WRITE);
+ return;
+ case 0x09:
+ /* WRITE_DELETED variants */
+// FLOPPY_DPRINTF("treat WRITE_DELETED command\n");
+ FLOPPY_ERROR("treat WRITE_DELETED command\n");
+ fdctrl_start_transfer_del(fdctrl, FD_DIR_WRITE);
+ return;
+ default:
+ break;
+ }
+ switch (fdctrl->fifo[0]) {
+ case 0x03:
+ /* SPECIFY */
+ FLOPPY_DPRINTF("treat SPECIFY command\n");
+ fdctrl->timer0 = (fdctrl->fifo[1] >> 4) & 0xF;
+ fdctrl->timer1 = fdctrl->fifo[2] >> 1;
+ fdctrl->dma_en = 1 - (fdctrl->fifo[2] & 1) ;
+ /* No result back */
+ fdctrl_reset_fifo(fdctrl);
+ break;
+ case 0x04:
+ /* SENSE_DRIVE_STATUS */
+ FLOPPY_DPRINTF("treat SENSE_DRIVE_STATUS command\n");
+ fdctrl->cur_drv = fdctrl->fifo[1] & 1;
+ cur_drv = get_cur_drv(fdctrl);
+ cur_drv->head = (fdctrl->fifo[1] >> 2) & 1;
+ /* 1 Byte status back */
+ fdctrl->fifo[0] = (cur_drv->ro << 6) |
+ (cur_drv->track == 0 ? 0x10 : 0x00) |
+ (cur_drv->head << 2) |
+ fdctrl->cur_drv |
+ 0x28;
+ fdctrl_set_fifo(fdctrl, 1, 0);
+ break;
+ case 0x07:
+ /* RECALIBRATE */
+ FLOPPY_DPRINTF("treat RECALIBRATE command\n");
+ fdctrl->cur_drv = fdctrl->fifo[1] & 1;
+ cur_drv = get_cur_drv(fdctrl);
+ fd_recalibrate(cur_drv);
+ fdctrl_reset_fifo(fdctrl);
+ /* Raise Interrupt */
+ fdctrl_raise_irq(fdctrl, 0x20);
+ break;
+ case 0x0F:
+ /* SEEK */
+ FLOPPY_DPRINTF("treat SEEK command\n");
+ fdctrl->cur_drv = fdctrl->fifo[1] & 1;
+ cur_drv = get_cur_drv(fdctrl);
+ fd_start(cur_drv);
+ if (fdctrl->fifo[2] <= cur_drv->track)
+ cur_drv->dir = 1;
+ else
+ cur_drv->dir = 0;
+ fdctrl_reset_fifo(fdctrl);
+ if (fdctrl->fifo[2] > cur_drv->max_track) {
+ fdctrl_raise_irq(fdctrl, 0x60);
+ } else {
+ cur_drv->track = fdctrl->fifo[2];
+ /* Raise Interrupt */
+ fdctrl_raise_irq(fdctrl, 0x20);
+ }
+ break;
+ case 0x12:
+ /* PERPENDICULAR_MODE */
+ FLOPPY_DPRINTF("treat PERPENDICULAR_MODE command\n");
+ if (fdctrl->fifo[1] & 0x80)
+ cur_drv->perpendicular = fdctrl->fifo[1] & 0x7;
+ /* No result back */
+ fdctrl_reset_fifo(fdctrl);
+ break;
+ case 0x13:
+ /* CONFIGURE */
+ FLOPPY_DPRINTF("treat CONFIGURE command\n");
+ fdctrl->config = fdctrl->fifo[2];
+ fdctrl->precomp_trk = fdctrl->fifo[3];
+ /* No result back */
+ fdctrl_reset_fifo(fdctrl);
+ break;
+ case 0x17:
+ /* POWERDOWN_MODE */
+ FLOPPY_DPRINTF("treat POWERDOWN_MODE command\n");
+ fdctrl->pwrd = fdctrl->fifo[1];
+ fdctrl->fifo[0] = fdctrl->fifo[1];
+ fdctrl_set_fifo(fdctrl, 1, 1);
+ break;
+ case 0x33:
+ /* OPTION */
+ FLOPPY_DPRINTF("treat OPTION command\n");
+ /* No result back */
+ fdctrl_reset_fifo(fdctrl);
+ break;
+ case 0x42:
+ /* READ_TRACK */
+// FLOPPY_DPRINTF("treat READ_TRACK command\n");
+ FLOPPY_ERROR("treat READ_TRACK command\n");
+ fdctrl_start_transfer(fdctrl, FD_DIR_READ);
+ break;
+ case 0x4A:
+ /* READ_ID */
+ FLOPPY_DPRINTF("treat READ_ID command\n");
+ /* XXX: should set main status register to busy */
+ cur_drv->head = (fdctrl->fifo[1] >> 2) & 1;
+ qemu_mod_timer(fdctrl->result_timer,
+ qemu_get_clock(vm_clock) + (ticks_per_sec / 50));
+ break;
+ case 0x4C:
+ /* RESTORE */
+ FLOPPY_DPRINTF("treat RESTORE command\n");
+ /* Drives position */
+ drv0(fdctrl)->track = fdctrl->fifo[3];
+ drv1(fdctrl)->track = fdctrl->fifo[4];
+ /* timers */
+ fdctrl->timer0 = fdctrl->fifo[7];
+ fdctrl->timer1 = fdctrl->fifo[8];
+ cur_drv->last_sect = fdctrl->fifo[9];
+ fdctrl->lock = fdctrl->fifo[10] >> 7;
+ cur_drv->perpendicular = (fdctrl->fifo[10] >> 2) & 0xF;
+ fdctrl->config = fdctrl->fifo[11];
+ fdctrl->precomp_trk = fdctrl->fifo[12];
+ fdctrl->pwrd = fdctrl->fifo[13];
+ fdctrl_reset_fifo(fdctrl);
+ break;
+ case 0x4D:
+ /* FORMAT_TRACK */
+ FLOPPY_DPRINTF("treat FORMAT_TRACK command\n");
+ fdctrl->cur_drv = fdctrl->fifo[1] & 1;
+ cur_drv = get_cur_drv(fdctrl);
+ fdctrl->data_state |= FD_STATE_FORMAT;
+ if (fdctrl->fifo[0] & 0x80)
+ fdctrl->data_state |= FD_STATE_MULTI;
+ else
+ fdctrl->data_state &= ~FD_STATE_MULTI;
+ fdctrl->data_state &= ~FD_STATE_SEEK;
+ cur_drv->bps =
+ fdctrl->fifo[2] > 7 ? 16384 : 128 << fdctrl->fifo[2];
+#if 0
+ cur_drv->last_sect =
+ cur_drv->flags & FDISK_DBL_SIDES ? fdctrl->fifo[3] :
+ fdctrl->fifo[3] / 2;
+#else
+ cur_drv->last_sect = fdctrl->fifo[3];
+#endif
+ /* Bochs BIOS is buggy and don't send format informations
+ * for each sector. So, pretend all's done right now...
+ */
+ fdctrl->data_state &= ~FD_STATE_FORMAT;
+ fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
+ break;
+ case 0x8E:
+ /* DRIVE_SPECIFICATION_COMMAND */
+ FLOPPY_DPRINTF("treat DRIVE_SPECIFICATION_COMMAND command\n");
+ if (fdctrl->fifo[fdctrl->data_pos - 1] & 0x80) {
+ /* Command parameters done */
+ if (fdctrl->fifo[fdctrl->data_pos - 1] & 0x40) {
+ fdctrl->fifo[0] = fdctrl->fifo[1];
+ fdctrl->fifo[2] = 0;
+ fdctrl->fifo[3] = 0;
+ fdctrl_set_fifo(fdctrl, 4, 1);
+ } else {
+ fdctrl_reset_fifo(fdctrl);
+ }
+ } else if (fdctrl->data_len > 7) {
+ /* ERROR */
+ fdctrl->fifo[0] = 0x80 |
+ (cur_drv->head << 2) | fdctrl->cur_drv;
+ fdctrl_set_fifo(fdctrl, 1, 1);
+ }
+ break;
+ case 0x8F:
+ /* RELATIVE_SEEK_OUT */
+ FLOPPY_DPRINTF("treat RELATIVE_SEEK_OUT command\n");
+ fdctrl->cur_drv = fdctrl->fifo[1] & 1;
+ cur_drv = get_cur_drv(fdctrl);
+ fd_start(cur_drv);
+ cur_drv->dir = 0;
+ if (fdctrl->fifo[2] + cur_drv->track >= cur_drv->max_track) {
+ cur_drv->track = cur_drv->max_track - 1;
+ } else {
+ cur_drv->track += fdctrl->fifo[2];
+ }
+ fdctrl_reset_fifo(fdctrl);
+ fdctrl_raise_irq(fdctrl, 0x20);
+ break;
+ case 0xCD:
+ /* FORMAT_AND_WRITE */
+// FLOPPY_DPRINTF("treat FORMAT_AND_WRITE command\n");
+ FLOPPY_ERROR("treat FORMAT_AND_WRITE command\n");
+ fdctrl_unimplemented(fdctrl);
+ break;
+ case 0xCF:
+ /* RELATIVE_SEEK_IN */
+ FLOPPY_DPRINTF("treat RELATIVE_SEEK_IN command\n");
+ fdctrl->cur_drv = fdctrl->fifo[1] & 1;
+ cur_drv = get_cur_drv(fdctrl);
+ fd_start(cur_drv);
+ cur_drv->dir = 1;
+ if (fdctrl->fifo[2] > cur_drv->track) {
+ cur_drv->track = 0;
+ } else {
+ cur_drv->track -= fdctrl->fifo[2];
+ }
+ fdctrl_reset_fifo(fdctrl);
+ /* Raise Interrupt */
+ fdctrl_raise_irq(fdctrl, 0x20);
+ break;
+ }
+ }
+}
+
+static void fdctrl_result_timer(void *opaque)
+{
+ fdctrl_t *fdctrl = opaque;
+ fdctrl_stop_transfer(fdctrl, 0x00, 0x00, 0x00);
+}
--- /dev/null
+/*
+**
+** File: fmopl.c -- software implementation of FM sound generator
+**
+** Copyright (C) 1999,2000 Tatsuyuki Satoh , MultiArcadeMachineEmurator development
+**
+** Version 0.37a
+**
+*/
+
+/*
+ preliminary :
+ Problem :
+ note:
+*/
+
+/* This version of fmopl.c is a fork of the MAME one, relicensed under the LGPL.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#define INLINE __inline
+#define HAS_YM3812 1
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <math.h>
+//#include "driver.h" /* use M.A.M.E. */
+#include "fmopl.h"
+
+#ifndef PI
+#define PI 3.14159265358979323846
+#endif
+
+/* -------------------- for debug --------------------- */
+/* #define OPL_OUTPUT_LOG */
+#ifdef OPL_OUTPUT_LOG
+static FILE *opl_dbg_fp = NULL;
+static FM_OPL *opl_dbg_opl[16];
+static int opl_dbg_maxchip,opl_dbg_chip;
+#endif
+
+/* -------------------- preliminary define section --------------------- */
+/* attack/decay rate time rate */
+#define OPL_ARRATE 141280 /* RATE 4 = 2826.24ms @ 3.6MHz */
+#define OPL_DRRATE 1956000 /* RATE 4 = 39280.64ms @ 3.6MHz */
+
+#define DELTAT_MIXING_LEVEL (1) /* DELTA-T ADPCM MIXING LEVEL */
+
+#define FREQ_BITS 24 /* frequency turn */
+
+/* counter bits = 20 , octerve 7 */
+#define FREQ_RATE (1<<(FREQ_BITS-20))
+#define TL_BITS (FREQ_BITS+2)
+
+/* final output shift , limit minimum and maximum */
+#define OPL_OUTSB (TL_BITS+3-16) /* OPL output final shift 16bit */
+#define OPL_MAXOUT (0x7fff<<OPL_OUTSB)
+#define OPL_MINOUT (-0x8000<<OPL_OUTSB)
+
+/* -------------------- quality selection --------------------- */
+
+/* sinwave entries */
+/* used static memory = SIN_ENT * 4 (byte) */
+#define SIN_ENT 2048
+
+/* output level entries (envelope,sinwave) */
+/* envelope counter lower bits */
+#define ENV_BITS 16
+/* envelope output entries */
+#define EG_ENT 4096
+/* used dynamic memory = EG_ENT*4*4(byte)or EG_ENT*6*4(byte) */
+/* used static memory = EG_ENT*4 (byte) */
+
+#define EG_OFF ((2*EG_ENT)<<ENV_BITS) /* OFF */
+#define EG_DED EG_OFF
+#define EG_DST (EG_ENT<<ENV_BITS) /* DECAY START */
+#define EG_AED EG_DST
+#define EG_AST 0 /* ATTACK START */
+
+#define EG_STEP (96.0/EG_ENT) /* OPL is 0.1875 dB step */
+
+/* LFO table entries */
+#define VIB_ENT 512
+#define VIB_SHIFT (32-9)
+#define AMS_ENT 512
+#define AMS_SHIFT (32-9)
+
+#define VIB_RATE 256
+
+/* -------------------- local defines , macros --------------------- */
+
+/* register number to channel number , slot offset */
+#define SLOT1 0
+#define SLOT2 1
+
+/* envelope phase */
+#define ENV_MOD_RR 0x00
+#define ENV_MOD_DR 0x01
+#define ENV_MOD_AR 0x02
+
+/* -------------------- tables --------------------- */
+static const int slot_array[32]=
+{
+ 0, 2, 4, 1, 3, 5,-1,-1,
+ 6, 8,10, 7, 9,11,-1,-1,
+ 12,14,16,13,15,17,-1,-1,
+ -1,-1,-1,-1,-1,-1,-1,-1
+};
+
+/* key scale level */
+/* table is 3dB/OCT , DV converts this in TL step at 6dB/OCT */
+#define DV (EG_STEP/2)
+static const UINT32 KSL_TABLE[8*16]=
+{
+ /* OCT 0 */
+ 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
+ 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
+ 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
+ 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
+ /* OCT 1 */
+ 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
+ 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
+ 0.000/DV, 0.750/DV, 1.125/DV, 1.500/DV,
+ 1.875/DV, 2.250/DV, 2.625/DV, 3.000/DV,
+ /* OCT 2 */
+ 0.000/DV, 0.000/DV, 0.000/DV, 0.000/DV,
+ 0.000/DV, 1.125/DV, 1.875/DV, 2.625/DV,
+ 3.000/DV, 3.750/DV, 4.125/DV, 4.500/DV,
+ 4.875/DV, 5.250/DV, 5.625/DV, 6.000/DV,
+ /* OCT 3 */
+ 0.000/DV, 0.000/DV, 0.000/DV, 1.875/DV,
+ 3.000/DV, 4.125/DV, 4.875/DV, 5.625/DV,
+ 6.000/DV, 6.750/DV, 7.125/DV, 7.500/DV,
+ 7.875/DV, 8.250/DV, 8.625/DV, 9.000/DV,
+ /* OCT 4 */
+ 0.000/DV, 0.000/DV, 3.000/DV, 4.875/DV,
+ 6.000/DV, 7.125/DV, 7.875/DV, 8.625/DV,
+ 9.000/DV, 9.750/DV,10.125/DV,10.500/DV,
+ 10.875/DV,11.250/DV,11.625/DV,12.000/DV,
+ /* OCT 5 */
+ 0.000/DV, 3.000/DV, 6.000/DV, 7.875/DV,
+ 9.000/DV,10.125/DV,10.875/DV,11.625/DV,
+ 12.000/DV,12.750/DV,13.125/DV,13.500/DV,
+ 13.875/DV,14.250/DV,14.625/DV,15.000/DV,
+ /* OCT 6 */
+ 0.000/DV, 6.000/DV, 9.000/DV,10.875/DV,
+ 12.000/DV,13.125/DV,13.875/DV,14.625/DV,
+ 15.000/DV,15.750/DV,16.125/DV,16.500/DV,
+ 16.875/DV,17.250/DV,17.625/DV,18.000/DV,
+ /* OCT 7 */
+ 0.000/DV, 9.000/DV,12.000/DV,13.875/DV,
+ 15.000/DV,16.125/DV,16.875/DV,17.625/DV,
+ 18.000/DV,18.750/DV,19.125/DV,19.500/DV,
+ 19.875/DV,20.250/DV,20.625/DV,21.000/DV
+};
+#undef DV
+
+/* sustain lebel table (3db per step) */
+/* 0 - 15: 0, 3, 6, 9,12,15,18,21,24,27,30,33,36,39,42,93 (dB)*/
+#define SC(db) (db*((3/EG_STEP)*(1<<ENV_BITS)))+EG_DST
+static const INT32 SL_TABLE[16]={
+ SC( 0),SC( 1),SC( 2),SC(3 ),SC(4 ),SC(5 ),SC(6 ),SC( 7),
+ SC( 8),SC( 9),SC(10),SC(11),SC(12),SC(13),SC(14),SC(31)
+};
+#undef SC
+
+#define TL_MAX (EG_ENT*2) /* limit(tl + ksr + envelope) + sinwave */
+/* TotalLevel : 48 24 12 6 3 1.5 0.75 (dB) */
+/* TL_TABLE[ 0 to TL_MAX ] : plus section */
+/* TL_TABLE[ TL_MAX to TL_MAX+TL_MAX-1 ] : minus section */
+static INT32 *TL_TABLE;
+
+/* pointers to TL_TABLE with sinwave output offset */
+static INT32 **SIN_TABLE;
+
+/* LFO table */
+static INT32 *AMS_TABLE;
+static INT32 *VIB_TABLE;
+
+/* envelope output curve table */
+/* attack + decay + OFF */
+static INT32 ENV_CURVE[2*EG_ENT+1];
+
+/* multiple table */
+#define ML 2
+static const UINT32 MUL_TABLE[16]= {
+/* 1/2, 1, 2, 3, 4, 5, 6, 7, 8, 9,10,11,12,13,14,15 */
+ 0.50*ML, 1.00*ML, 2.00*ML, 3.00*ML, 4.00*ML, 5.00*ML, 6.00*ML, 7.00*ML,
+ 8.00*ML, 9.00*ML,10.00*ML,10.00*ML,12.00*ML,12.00*ML,15.00*ML,15.00*ML
+};
+#undef ML
+
+/* dummy attack / decay rate ( when rate == 0 ) */
+static INT32 RATE_0[16]=
+{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
+
+/* -------------------- static state --------------------- */
+
+/* lock level of common table */
+static int num_lock = 0;
+
+/* work table */
+static void *cur_chip = NULL; /* current chip point */
+/* currenct chip state */
+/* static OPLSAMPLE *bufL,*bufR; */
+static OPL_CH *S_CH;
+static OPL_CH *E_CH;
+OPL_SLOT *SLOT7_1,*SLOT7_2,*SLOT8_1,*SLOT8_2;
+
+static INT32 outd[1];
+static INT32 ams;
+static INT32 vib;
+INT32 *ams_table;
+INT32 *vib_table;
+static INT32 amsIncr;
+static INT32 vibIncr;
+static INT32 feedback2; /* connect for SLOT 2 */
+
+/* log output level */
+#define LOG_ERR 3 /* ERROR */
+#define LOG_WAR 2 /* WARNING */
+#define LOG_INF 1 /* INFORMATION */
+
+//#define LOG_LEVEL LOG_INF
+#define LOG_LEVEL LOG_ERR
+
+//#define LOG(n,x) if( (n)>=LOG_LEVEL ) logerror x
+#define LOG(n,x)
+
+/* --------------------- subroutines --------------------- */
+
+INLINE int Limit( int val, int max, int min ) {
+ if ( val > max )
+ val = max;
+ else if ( val < min )
+ val = min;
+
+ return val;
+}
+
+/* status set and IRQ handling */
+INLINE void OPL_STATUS_SET(FM_OPL *OPL,int flag)
+{
+ /* set status flag */
+ OPL->status |= flag;
+ if(!(OPL->status & 0x80))
+ {
+ if(OPL->status & OPL->statusmask)
+ { /* IRQ on */
+ OPL->status |= 0x80;
+ /* callback user interrupt handler (IRQ is OFF to ON) */
+ if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,1);
+ }
+ }
+}
+
+/* status reset and IRQ handling */
+INLINE void OPL_STATUS_RESET(FM_OPL *OPL,int flag)
+{
+ /* reset status flag */
+ OPL->status &=~flag;
+ if((OPL->status & 0x80))
+ {
+ if (!(OPL->status & OPL->statusmask) )
+ {
+ OPL->status &= 0x7f;
+ /* callback user interrupt handler (IRQ is ON to OFF) */
+ if(OPL->IRQHandler) (OPL->IRQHandler)(OPL->IRQParam,0);
+ }
+ }
+}
+
+/* IRQ mask set */
+INLINE void OPL_STATUSMASK_SET(FM_OPL *OPL,int flag)
+{
+ OPL->statusmask = flag;
+ /* IRQ handling check */
+ OPL_STATUS_SET(OPL,0);
+ OPL_STATUS_RESET(OPL,0);
+}
+
+/* ----- key on ----- */
+INLINE void OPL_KEYON(OPL_SLOT *SLOT)
+{
+ /* sin wave restart */
+ SLOT->Cnt = 0;
+ /* set attack */
+ SLOT->evm = ENV_MOD_AR;
+ SLOT->evs = SLOT->evsa;
+ SLOT->evc = EG_AST;
+ SLOT->eve = EG_AED;
+}
+/* ----- key off ----- */
+INLINE void OPL_KEYOFF(OPL_SLOT *SLOT)
+{
+ if( SLOT->evm > ENV_MOD_RR)
+ {
+ /* set envelope counter from envleope output */
+ SLOT->evm = ENV_MOD_RR;
+ if( !(SLOT->evc&EG_DST) )
+ //SLOT->evc = (ENV_CURVE[SLOT->evc>>ENV_BITS]<<ENV_BITS) + EG_DST;
+ SLOT->evc = EG_DST;
+ SLOT->eve = EG_DED;
+ SLOT->evs = SLOT->evsr;
+ }
+}
+
+/* ---------- calcrate Envelope Generator & Phase Generator ---------- */
+/* return : envelope output */
+INLINE UINT32 OPL_CALC_SLOT( OPL_SLOT *SLOT )
+{
+ /* calcrate envelope generator */
+ if( (SLOT->evc+=SLOT->evs) >= SLOT->eve )
+ {
+ switch( SLOT->evm ){
+ case ENV_MOD_AR: /* ATTACK -> DECAY1 */
+ /* next DR */
+ SLOT->evm = ENV_MOD_DR;
+ SLOT->evc = EG_DST;
+ SLOT->eve = SLOT->SL;
+ SLOT->evs = SLOT->evsd;
+ break;
+ case ENV_MOD_DR: /* DECAY -> SL or RR */
+ SLOT->evc = SLOT->SL;
+ SLOT->eve = EG_DED;
+ if(SLOT->eg_typ)
+ {
+ SLOT->evs = 0;
+ }
+ else
+ {
+ SLOT->evm = ENV_MOD_RR;
+ SLOT->evs = SLOT->evsr;
+ }
+ break;
+ case ENV_MOD_RR: /* RR -> OFF */
+ SLOT->evc = EG_OFF;
+ SLOT->eve = EG_OFF+1;
+ SLOT->evs = 0;
+ break;
+ }
+ }
+ /* calcrate envelope */
+ return SLOT->TLL+ENV_CURVE[SLOT->evc>>ENV_BITS]+(SLOT->ams ? ams : 0);
+}
+
+/* set algorythm connection */
+static void set_algorythm( OPL_CH *CH)
+{
+ INT32 *carrier = &outd[0];
+ CH->connect1 = CH->CON ? carrier : &feedback2;
+ CH->connect2 = carrier;
+}
+
+/* ---------- frequency counter for operater update ---------- */
+INLINE void CALC_FCSLOT(OPL_CH *CH,OPL_SLOT *SLOT)
+{
+ int ksr;
+
+ /* frequency step counter */
+ SLOT->Incr = CH->fc * SLOT->mul;
+ ksr = CH->kcode >> SLOT->KSR;
+
+ if( SLOT->ksr != ksr )
+ {
+ SLOT->ksr = ksr;
+ /* attack , decay rate recalcration */
+ SLOT->evsa = SLOT->AR[ksr];
+ SLOT->evsd = SLOT->DR[ksr];
+ SLOT->evsr = SLOT->RR[ksr];
+ }
+ SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);
+}
+
+/* set multi,am,vib,EG-TYP,KSR,mul */
+INLINE void set_mul(FM_OPL *OPL,int slot,int v)
+{
+ OPL_CH *CH = &OPL->P_CH[slot/2];
+ OPL_SLOT *SLOT = &CH->SLOT[slot&1];
+
+ SLOT->mul = MUL_TABLE[v&0x0f];
+ SLOT->KSR = (v&0x10) ? 0 : 2;
+ SLOT->eg_typ = (v&0x20)>>5;
+ SLOT->vib = (v&0x40);
+ SLOT->ams = (v&0x80);
+ CALC_FCSLOT(CH,SLOT);
+}
+
+/* set ksl & tl */
+INLINE void set_ksl_tl(FM_OPL *OPL,int slot,int v)
+{
+ OPL_CH *CH = &OPL->P_CH[slot/2];
+ OPL_SLOT *SLOT = &CH->SLOT[slot&1];
+ int ksl = v>>6; /* 0 / 1.5 / 3 / 6 db/OCT */
+
+ SLOT->ksl = ksl ? 3-ksl : 31;
+ SLOT->TL = (v&0x3f)*(0.75/EG_STEP); /* 0.75db step */
+
+ if( !(OPL->mode&0x80) )
+ { /* not CSM latch total level */
+ SLOT->TLL = SLOT->TL + (CH->ksl_base>>SLOT->ksl);
+ }
+}
+
+/* set attack rate & decay rate */
+INLINE void set_ar_dr(FM_OPL *OPL,int slot,int v)
+{
+ OPL_CH *CH = &OPL->P_CH[slot/2];
+ OPL_SLOT *SLOT = &CH->SLOT[slot&1];
+ int ar = v>>4;
+ int dr = v&0x0f;
+
+ SLOT->AR = ar ? &OPL->AR_TABLE[ar<<2] : RATE_0;
+ SLOT->evsa = SLOT->AR[SLOT->ksr];
+ if( SLOT->evm == ENV_MOD_AR ) SLOT->evs = SLOT->evsa;
+
+ SLOT->DR = dr ? &OPL->DR_TABLE[dr<<2] : RATE_0;
+ SLOT->evsd = SLOT->DR[SLOT->ksr];
+ if( SLOT->evm == ENV_MOD_DR ) SLOT->evs = SLOT->evsd;
+}
+
+/* set sustain level & release rate */
+INLINE void set_sl_rr(FM_OPL *OPL,int slot,int v)
+{
+ OPL_CH *CH = &OPL->P_CH[slot/2];
+ OPL_SLOT *SLOT = &CH->SLOT[slot&1];
+ int sl = v>>4;
+ int rr = v & 0x0f;
+
+ SLOT->SL = SL_TABLE[sl];
+ if( SLOT->evm == ENV_MOD_DR ) SLOT->eve = SLOT->SL;
+ SLOT->RR = &OPL->DR_TABLE[rr<<2];
+ SLOT->evsr = SLOT->RR[SLOT->ksr];
+ if( SLOT->evm == ENV_MOD_RR ) SLOT->evs = SLOT->evsr;
+}
+
+/* operator output calcrator */
+#define OP_OUT(slot,env,con) slot->wavetable[((slot->Cnt+con)/(0x1000000/SIN_ENT))&(SIN_ENT-1)][env]
+/* ---------- calcrate one of channel ---------- */
+INLINE void OPL_CALC_CH( OPL_CH *CH )
+{
+ UINT32 env_out;
+ OPL_SLOT *SLOT;
+
+ feedback2 = 0;
+ /* SLOT 1 */
+ SLOT = &CH->SLOT[SLOT1];
+ env_out=OPL_CALC_SLOT(SLOT);
+ if( env_out < EG_ENT-1 )
+ {
+ /* PG */
+ if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE);
+ else SLOT->Cnt += SLOT->Incr;
+ /* connectoion */
+ if(CH->FB)
+ {
+ int feedback1 = (CH->op1_out[0]+CH->op1_out[1])>>CH->FB;
+ CH->op1_out[1] = CH->op1_out[0];
+ *CH->connect1 += CH->op1_out[0] = OP_OUT(SLOT,env_out,feedback1);
+ }
+ else
+ {
+ *CH->connect1 += OP_OUT(SLOT,env_out,0);
+ }
+ }else
+ {
+ CH->op1_out[1] = CH->op1_out[0];
+ CH->op1_out[0] = 0;
+ }
+ /* SLOT 2 */
+ SLOT = &CH->SLOT[SLOT2];
+ env_out=OPL_CALC_SLOT(SLOT);
+ if( env_out < EG_ENT-1 )
+ {
+ /* PG */
+ if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE);
+ else SLOT->Cnt += SLOT->Incr;
+ /* connectoion */
+ outd[0] += OP_OUT(SLOT,env_out, feedback2);
+ }
+}
+
+/* ---------- calcrate rythm block ---------- */
+#define WHITE_NOISE_db 6.0
+INLINE void OPL_CALC_RH( OPL_CH *CH )
+{
+ UINT32 env_tam,env_sd,env_top,env_hh;
+ int whitenoise = (rand()&1)*(WHITE_NOISE_db/EG_STEP);
+ INT32 tone8;
+
+ OPL_SLOT *SLOT;
+ int env_out;
+
+ /* BD : same as FM serial mode and output level is large */
+ feedback2 = 0;
+ /* SLOT 1 */
+ SLOT = &CH[6].SLOT[SLOT1];
+ env_out=OPL_CALC_SLOT(SLOT);
+ if( env_out < EG_ENT-1 )
+ {
+ /* PG */
+ if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE);
+ else SLOT->Cnt += SLOT->Incr;
+ /* connectoion */
+ if(CH[6].FB)
+ {
+ int feedback1 = (CH[6].op1_out[0]+CH[6].op1_out[1])>>CH[6].FB;
+ CH[6].op1_out[1] = CH[6].op1_out[0];
+ feedback2 = CH[6].op1_out[0] = OP_OUT(SLOT,env_out,feedback1);
+ }
+ else
+ {
+ feedback2 = OP_OUT(SLOT,env_out,0);
+ }
+ }else
+ {
+ feedback2 = 0;
+ CH[6].op1_out[1] = CH[6].op1_out[0];
+ CH[6].op1_out[0] = 0;
+ }
+ /* SLOT 2 */
+ SLOT = &CH[6].SLOT[SLOT2];
+ env_out=OPL_CALC_SLOT(SLOT);
+ if( env_out < EG_ENT-1 )
+ {
+ /* PG */
+ if(SLOT->vib) SLOT->Cnt += (SLOT->Incr*vib/VIB_RATE);
+ else SLOT->Cnt += SLOT->Incr;
+ /* connectoion */
+ outd[0] += OP_OUT(SLOT,env_out, feedback2)*2;
+ }
+
+ // SD (17) = mul14[fnum7] + white noise
+ // TAM (15) = mul15[fnum8]
+ // TOP (18) = fnum6(mul18[fnum8]+whitenoise)
+ // HH (14) = fnum7(mul18[fnum8]+whitenoise) + white noise
+ env_sd =OPL_CALC_SLOT(SLOT7_2) + whitenoise;
+ env_tam=OPL_CALC_SLOT(SLOT8_1);
+ env_top=OPL_CALC_SLOT(SLOT8_2);
+ env_hh =OPL_CALC_SLOT(SLOT7_1) + whitenoise;
+
+ /* PG */
+ if(SLOT7_1->vib) SLOT7_1->Cnt += (2*SLOT7_1->Incr*vib/VIB_RATE);
+ else SLOT7_1->Cnt += 2*SLOT7_1->Incr;
+ if(SLOT7_2->vib) SLOT7_2->Cnt += ((CH[7].fc*8)*vib/VIB_RATE);
+ else SLOT7_2->Cnt += (CH[7].fc*8);
+ if(SLOT8_1->vib) SLOT8_1->Cnt += (SLOT8_1->Incr*vib/VIB_RATE);
+ else SLOT8_1->Cnt += SLOT8_1->Incr;
+ if(SLOT8_2->vib) SLOT8_2->Cnt += ((CH[8].fc*48)*vib/VIB_RATE);
+ else SLOT8_2->Cnt += (CH[8].fc*48);
+
+ tone8 = OP_OUT(SLOT8_2,whitenoise,0 );
+
+ /* SD */
+ if( env_sd < EG_ENT-1 )
+ outd[0] += OP_OUT(SLOT7_1,env_sd, 0)*8;
+ /* TAM */
+ if( env_tam < EG_ENT-1 )
+ outd[0] += OP_OUT(SLOT8_1,env_tam, 0)*2;
+ /* TOP-CY */
+ if( env_top < EG_ENT-1 )
+ outd[0] += OP_OUT(SLOT7_2,env_top,tone8)*2;
+ /* HH */
+ if( env_hh < EG_ENT-1 )
+ outd[0] += OP_OUT(SLOT7_2,env_hh,tone8)*2;
+}
+
+/* ----------- initialize time tabls ----------- */
+static void init_timetables( FM_OPL *OPL , int ARRATE , int DRRATE )
+{
+ int i;
+ double rate;
+
+ /* make attack rate & decay rate tables */
+ for (i = 0;i < 4;i++) OPL->AR_TABLE[i] = OPL->DR_TABLE[i] = 0;
+ for (i = 4;i <= 60;i++){
+ rate = OPL->freqbase; /* frequency rate */
+ if( i < 60 ) rate *= 1.0+(i&3)*0.25; /* b0-1 : x1 , x1.25 , x1.5 , x1.75 */
+ rate *= 1<<((i>>2)-1); /* b2-5 : shift bit */
+ rate *= (double)(EG_ENT<<ENV_BITS);
+ OPL->AR_TABLE[i] = rate / ARRATE;
+ OPL->DR_TABLE[i] = rate / DRRATE;
+ }
+ for (i = 60;i < 76;i++)
+ {
+ OPL->AR_TABLE[i] = EG_AED-1;
+ OPL->DR_TABLE[i] = OPL->DR_TABLE[60];
+ }
+#if 0
+ for (i = 0;i < 64 ;i++){ /* make for overflow area */
+ LOG(LOG_WAR,("rate %2d , ar %f ms , dr %f ms \n",i,
+ ((double)(EG_ENT<<ENV_BITS) / OPL->AR_TABLE[i]) * (1000.0 / OPL->rate),
+ ((double)(EG_ENT<<ENV_BITS) / OPL->DR_TABLE[i]) * (1000.0 / OPL->rate) ));
+ }
+#endif
+}
+
+/* ---------- generic table initialize ---------- */
+static int OPLOpenTable( void )
+{
+ int s,t;
+ double rate;
+ int i,j;
+ double pom;
+
+ /* allocate dynamic tables */
+ if( (TL_TABLE = malloc(TL_MAX*2*sizeof(INT32))) == NULL)
+ return 0;
+ if( (SIN_TABLE = malloc(SIN_ENT*4 *sizeof(INT32 *))) == NULL)
+ {
+ free(TL_TABLE);
+ return 0;
+ }
+ if( (AMS_TABLE = malloc(AMS_ENT*2 *sizeof(INT32))) == NULL)
+ {
+ free(TL_TABLE);
+ free(SIN_TABLE);
+ return 0;
+ }
+ if( (VIB_TABLE = malloc(VIB_ENT*2 *sizeof(INT32))) == NULL)
+ {
+ free(TL_TABLE);
+ free(SIN_TABLE);
+ free(AMS_TABLE);
+ return 0;
+ }
+ /* make total level table */
+ for (t = 0;t < EG_ENT-1 ;t++){
+ rate = ((1<<TL_BITS)-1)/pow(10,EG_STEP*t/20); /* dB -> voltage */
+ TL_TABLE[ t] = (int)rate;
+ TL_TABLE[TL_MAX+t] = -TL_TABLE[t];
+/* LOG(LOG_INF,("TotalLevel(%3d) = %x\n",t,TL_TABLE[t]));*/
+ }
+ /* fill volume off area */
+ for ( t = EG_ENT-1; t < TL_MAX ;t++){
+ TL_TABLE[t] = TL_TABLE[TL_MAX+t] = 0;
+ }
+
+ /* make sinwave table (total level offet) */
+ /* degree 0 = degree 180 = off */
+ SIN_TABLE[0] = SIN_TABLE[SIN_ENT/2] = &TL_TABLE[EG_ENT-1];
+ for (s = 1;s <= SIN_ENT/4;s++){
+ pom = sin(2*PI*s/SIN_ENT); /* sin */
+ pom = 20*log10(1/pom); /* decibel */
+ j = pom / EG_STEP; /* TL_TABLE steps */
+
+ /* degree 0 - 90 , degree 180 - 90 : plus section */
+ SIN_TABLE[ s] = SIN_TABLE[SIN_ENT/2-s] = &TL_TABLE[j];
+ /* degree 180 - 270 , degree 360 - 270 : minus section */
+ SIN_TABLE[SIN_ENT/2+s] = SIN_TABLE[SIN_ENT -s] = &TL_TABLE[TL_MAX+j];
+/* LOG(LOG_INF,("sin(%3d) = %f:%f db\n",s,pom,(double)j * EG_STEP));*/
+ }
+ for (s = 0;s < SIN_ENT;s++)
+ {
+ SIN_TABLE[SIN_ENT*1+s] = s<(SIN_ENT/2) ? SIN_TABLE[s] : &TL_TABLE[EG_ENT];
+ SIN_TABLE[SIN_ENT*2+s] = SIN_TABLE[s % (SIN_ENT/2)];
+ SIN_TABLE[SIN_ENT*3+s] = (s/(SIN_ENT/4))&1 ? &TL_TABLE[EG_ENT] : SIN_TABLE[SIN_ENT*2+s];
+ }
+
+ /* envelope counter -> envelope output table */
+ for (i=0; i<EG_ENT; i++)
+ {
+ /* ATTACK curve */
+ pom = pow( ((double)(EG_ENT-1-i)/EG_ENT) , 8 ) * EG_ENT;
+ /* if( pom >= EG_ENT ) pom = EG_ENT-1; */
+ ENV_CURVE[i] = (int)pom;
+ /* DECAY ,RELEASE curve */
+ ENV_CURVE[(EG_DST>>ENV_BITS)+i]= i;
+ }
+ /* off */
+ ENV_CURVE[EG_OFF>>ENV_BITS]= EG_ENT-1;
+ /* make LFO ams table */
+ for (i=0; i<AMS_ENT; i++)
+ {
+ pom = (1.0+sin(2*PI*i/AMS_ENT))/2; /* sin */
+ AMS_TABLE[i] = (1.0/EG_STEP)*pom; /* 1dB */
+ AMS_TABLE[AMS_ENT+i] = (4.8/EG_STEP)*pom; /* 4.8dB */
+ }
+ /* make LFO vibrate table */
+ for (i=0; i<VIB_ENT; i++)
+ {
+ /* 100cent = 1seminote = 6% ?? */
+ pom = (double)VIB_RATE*0.06*sin(2*PI*i/VIB_ENT); /* +-100sect step */
+ VIB_TABLE[i] = VIB_RATE + (pom*0.07); /* +- 7cent */
+ VIB_TABLE[VIB_ENT+i] = VIB_RATE + (pom*0.14); /* +-14cent */
+ /* LOG(LOG_INF,("vib %d=%d\n",i,VIB_TABLE[VIB_ENT+i])); */
+ }
+ return 1;
+}
+
+
+static void OPLCloseTable( void )
+{
+ free(TL_TABLE);
+ free(SIN_TABLE);
+ free(AMS_TABLE);
+ free(VIB_TABLE);
+}
+
+/* CSM Key Controll */
+INLINE void CSMKeyControll(OPL_CH *CH)
+{
+ OPL_SLOT *slot1 = &CH->SLOT[SLOT1];
+ OPL_SLOT *slot2 = &CH->SLOT[SLOT2];
+ /* all key off */
+ OPL_KEYOFF(slot1);
+ OPL_KEYOFF(slot2);
+ /* total level latch */
+ slot1->TLL = slot1->TL + (CH->ksl_base>>slot1->ksl);
+ slot1->TLL = slot1->TL + (CH->ksl_base>>slot1->ksl);
+ /* key on */
+ CH->op1_out[0] = CH->op1_out[1] = 0;
+ OPL_KEYON(slot1);
+ OPL_KEYON(slot2);
+}
+
+/* ---------- opl initialize ---------- */
+static void OPL_initalize(FM_OPL *OPL)
+{
+ int fn;
+
+ /* frequency base */
+ OPL->freqbase = (OPL->rate) ? ((double)OPL->clock / OPL->rate) / 72 : 0;
+ /* Timer base time */
+ OPL->TimerBase = 1.0/((double)OPL->clock / 72.0 );
+ /* make time tables */
+ init_timetables( OPL , OPL_ARRATE , OPL_DRRATE );
+ /* make fnumber -> increment counter table */
+ for( fn=0 ; fn < 1024 ; fn++ )
+ {
+ OPL->FN_TABLE[fn] = OPL->freqbase * fn * FREQ_RATE * (1<<7) / 2;
+ }
+ /* LFO freq.table */
+ OPL->amsIncr = OPL->rate ? (double)AMS_ENT*(1<<AMS_SHIFT) / OPL->rate * 3.7 * ((double)OPL->clock/3600000) : 0;
+ OPL->vibIncr = OPL->rate ? (double)VIB_ENT*(1<<VIB_SHIFT) / OPL->rate * 6.4 * ((double)OPL->clock/3600000) : 0;
+}
+
+/* ---------- write a OPL registers ---------- */
+static void OPLWriteReg(FM_OPL *OPL, int r, int v)
+{
+ OPL_CH *CH;
+ int slot;
+ int block_fnum;
+
+ switch(r&0xe0)
+ {
+ case 0x00: /* 00-1f:controll */
+ switch(r&0x1f)
+ {
+ case 0x01:
+ /* wave selector enable */
+ if(OPL->type&OPL_TYPE_WAVESEL)
+ {
+ OPL->wavesel = v&0x20;
+ if(!OPL->wavesel)
+ {
+ /* preset compatible mode */
+ int c;
+ for(c=0;c<OPL->max_ch;c++)
+ {
+ OPL->P_CH[c].SLOT[SLOT1].wavetable = &SIN_TABLE[0];
+ OPL->P_CH[c].SLOT[SLOT2].wavetable = &SIN_TABLE[0];
+ }
+ }
+ }
+ return;
+ case 0x02: /* Timer 1 */
+ OPL->T[0] = (256-v)*4;
+ break;
+ case 0x03: /* Timer 2 */
+ OPL->T[1] = (256-v)*16;
+ return;
+ case 0x04: /* IRQ clear / mask and Timer enable */
+ if(v&0x80)
+ { /* IRQ flag clear */
+ OPL_STATUS_RESET(OPL,0x7f);
+ }
+ else
+ { /* set IRQ mask ,timer enable*/
+ UINT8 st1 = v&1;
+ UINT8 st2 = (v>>1)&1;
+ /* IRQRST,T1MSK,t2MSK,EOSMSK,BRMSK,x,ST2,ST1 */
+ OPL_STATUS_RESET(OPL,v&0x78);
+ OPL_STATUSMASK_SET(OPL,((~v)&0x78)|0x01);
+ /* timer 2 */
+ if(OPL->st[1] != st2)
+ {
+ double interval = st2 ? (double)OPL->T[1]*OPL->TimerBase : 0.0;
+ OPL->st[1] = st2;
+ if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+1,interval);
+ }
+ /* timer 1 */
+ if(OPL->st[0] != st1)
+ {
+ double interval = st1 ? (double)OPL->T[0]*OPL->TimerBase : 0.0;
+ OPL->st[0] = st1;
+ if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+0,interval);
+ }
+ }
+ return;
+#if BUILD_Y8950
+ case 0x06: /* Key Board OUT */
+ if(OPL->type&OPL_TYPE_KEYBOARD)
+ {
+ if(OPL->keyboardhandler_w)
+ OPL->keyboardhandler_w(OPL->keyboard_param,v);
+ else
+ LOG(LOG_WAR,("OPL:write unmapped KEYBOARD port\n"));
+ }
+ return;
+ case 0x07: /* DELTA-T controll : START,REC,MEMDATA,REPT,SPOFF,x,x,RST */
+ if(OPL->type&OPL_TYPE_ADPCM)
+ YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v);
+ return;
+ case 0x08: /* MODE,DELTA-T : CSM,NOTESEL,x,x,smpl,da/ad,64k,rom */
+ OPL->mode = v;
+ v&=0x1f; /* for DELTA-T unit */
+ case 0x09: /* START ADD */
+ case 0x0a:
+ case 0x0b: /* STOP ADD */
+ case 0x0c:
+ case 0x0d: /* PRESCALE */
+ case 0x0e:
+ case 0x0f: /* ADPCM data */
+ case 0x10: /* DELTA-N */
+ case 0x11: /* DELTA-N */
+ case 0x12: /* EG-CTRL */
+ if(OPL->type&OPL_TYPE_ADPCM)
+ YM_DELTAT_ADPCM_Write(OPL->deltat,r-0x07,v);
+ return;
+#if 0
+ case 0x15: /* DAC data */
+ case 0x16:
+ case 0x17: /* SHIFT */
+ return;
+ case 0x18: /* I/O CTRL (Direction) */
+ if(OPL->type&OPL_TYPE_IO)
+ OPL->portDirection = v&0x0f;
+ return;
+ case 0x19: /* I/O DATA */
+ if(OPL->type&OPL_TYPE_IO)
+ {
+ OPL->portLatch = v;
+ if(OPL->porthandler_w)
+ OPL->porthandler_w(OPL->port_param,v&OPL->portDirection);
+ }
+ return;
+ case 0x1a: /* PCM data */
+ return;
+#endif
+#endif
+ }
+ break;
+ case 0x20: /* am,vib,ksr,eg type,mul */
+ slot = slot_array[r&0x1f];
+ if(slot == -1) return;
+ set_mul(OPL,slot,v);
+ return;
+ case 0x40:
+ slot = slot_array[r&0x1f];
+ if(slot == -1) return;
+ set_ksl_tl(OPL,slot,v);
+ return;
+ case 0x60:
+ slot = slot_array[r&0x1f];
+ if(slot == -1) return;
+ set_ar_dr(OPL,slot,v);
+ return;
+ case 0x80:
+ slot = slot_array[r&0x1f];
+ if(slot == -1) return;
+ set_sl_rr(OPL,slot,v);
+ return;
+ case 0xa0:
+ switch(r)
+ {
+ case 0xbd:
+ /* amsep,vibdep,r,bd,sd,tom,tc,hh */
+ {
+ UINT8 rkey = OPL->rythm^v;
+ OPL->ams_table = &AMS_TABLE[v&0x80 ? AMS_ENT : 0];
+ OPL->vib_table = &VIB_TABLE[v&0x40 ? VIB_ENT : 0];
+ OPL->rythm = v&0x3f;
+ if(OPL->rythm&0x20)
+ {
+#if 0
+ usrintf_showmessage("OPL Rythm mode select");
+#endif
+ /* BD key on/off */
+ if(rkey&0x10)
+ {
+ if(v&0x10)
+ {
+ OPL->P_CH[6].op1_out[0] = OPL->P_CH[6].op1_out[1] = 0;
+ OPL_KEYON(&OPL->P_CH[6].SLOT[SLOT1]);
+ OPL_KEYON(&OPL->P_CH[6].SLOT[SLOT2]);
+ }
+ else
+ {
+ OPL_KEYOFF(&OPL->P_CH[6].SLOT[SLOT1]);
+ OPL_KEYOFF(&OPL->P_CH[6].SLOT[SLOT2]);
+ }
+ }
+ /* SD key on/off */
+ if(rkey&0x08)
+ {
+ if(v&0x08) OPL_KEYON(&OPL->P_CH[7].SLOT[SLOT2]);
+ else OPL_KEYOFF(&OPL->P_CH[7].SLOT[SLOT2]);
+ }/* TAM key on/off */
+ if(rkey&0x04)
+ {
+ if(v&0x04) OPL_KEYON(&OPL->P_CH[8].SLOT[SLOT1]);
+ else OPL_KEYOFF(&OPL->P_CH[8].SLOT[SLOT1]);
+ }
+ /* TOP-CY key on/off */
+ if(rkey&0x02)
+ {
+ if(v&0x02) OPL_KEYON(&OPL->P_CH[8].SLOT[SLOT2]);
+ else OPL_KEYOFF(&OPL->P_CH[8].SLOT[SLOT2]);
+ }
+ /* HH key on/off */
+ if(rkey&0x01)
+ {
+ if(v&0x01) OPL_KEYON(&OPL->P_CH[7].SLOT[SLOT1]);
+ else OPL_KEYOFF(&OPL->P_CH[7].SLOT[SLOT1]);
+ }
+ }
+ }
+ return;
+ }
+ /* keyon,block,fnum */
+ if( (r&0x0f) > 8) return;
+ CH = &OPL->P_CH[r&0x0f];
+ if(!(r&0x10))
+ { /* a0-a8 */
+ block_fnum = (CH->block_fnum&0x1f00) | v;
+ }
+ else
+ { /* b0-b8 */
+ int keyon = (v>>5)&1;
+ block_fnum = ((v&0x1f)<<8) | (CH->block_fnum&0xff);
+ if(CH->keyon != keyon)
+ {
+ if( (CH->keyon=keyon) )
+ {
+ CH->op1_out[0] = CH->op1_out[1] = 0;
+ OPL_KEYON(&CH->SLOT[SLOT1]);
+ OPL_KEYON(&CH->SLOT[SLOT2]);
+ }
+ else
+ {
+ OPL_KEYOFF(&CH->SLOT[SLOT1]);
+ OPL_KEYOFF(&CH->SLOT[SLOT2]);
+ }
+ }
+ }
+ /* update */
+ if(CH->block_fnum != block_fnum)
+ {
+ int blockRv = 7-(block_fnum>>10);
+ int fnum = block_fnum&0x3ff;
+ CH->block_fnum = block_fnum;
+
+ CH->ksl_base = KSL_TABLE[block_fnum>>6];
+ CH->fc = OPL->FN_TABLE[fnum]>>blockRv;
+ CH->kcode = CH->block_fnum>>9;
+ if( (OPL->mode&0x40) && CH->block_fnum&0x100) CH->kcode |=1;
+ CALC_FCSLOT(CH,&CH->SLOT[SLOT1]);
+ CALC_FCSLOT(CH,&CH->SLOT[SLOT2]);
+ }
+ return;
+ case 0xc0:
+ /* FB,C */
+ if( (r&0x0f) > 8) return;
+ CH = &OPL->P_CH[r&0x0f];
+ {
+ int feedback = (v>>1)&7;
+ CH->FB = feedback ? (8+1) - feedback : 0;
+ CH->CON = v&1;
+ set_algorythm(CH);
+ }
+ return;
+ case 0xe0: /* wave type */
+ slot = slot_array[r&0x1f];
+ if(slot == -1) return;
+ CH = &OPL->P_CH[slot/2];
+ if(OPL->wavesel)
+ {
+ /* LOG(LOG_INF,("OPL SLOT %d wave select %d\n",slot,v&3)); */
+ CH->SLOT[slot&1].wavetable = &SIN_TABLE[(v&0x03)*SIN_ENT];
+ }
+ return;
+ }
+}
+
+/* lock/unlock for common table */
+static int OPL_LockTable(void)
+{
+ num_lock++;
+ if(num_lock>1) return 0;
+ /* first time */
+ cur_chip = NULL;
+ /* allocate total level table (128kb space) */
+ if( !OPLOpenTable() )
+ {
+ num_lock--;
+ return -1;
+ }
+ return 0;
+}
+
+static void OPL_UnLockTable(void)
+{
+ if(num_lock) num_lock--;
+ if(num_lock) return;
+ /* last time */
+ cur_chip = NULL;
+ OPLCloseTable();
+}
+
+#if (BUILD_YM3812 || BUILD_YM3526)
+/*******************************************************************************/
+/* YM3812 local section */
+/*******************************************************************************/
+
+/* ---------- update one of chip ----------- */
+void YM3812UpdateOne(FM_OPL *OPL, INT16 *buffer, int length)
+{
+ int i;
+ int data;
+ OPLSAMPLE *buf = buffer;
+ UINT32 amsCnt = OPL->amsCnt;
+ UINT32 vibCnt = OPL->vibCnt;
+ UINT8 rythm = OPL->rythm&0x20;
+ OPL_CH *CH,*R_CH;
+
+ if( (void *)OPL != cur_chip ){
+ cur_chip = (void *)OPL;
+ /* channel pointers */
+ S_CH = OPL->P_CH;
+ E_CH = &S_CH[9];
+ /* rythm slot */
+ SLOT7_1 = &S_CH[7].SLOT[SLOT1];
+ SLOT7_2 = &S_CH[7].SLOT[SLOT2];
+ SLOT8_1 = &S_CH[8].SLOT[SLOT1];
+ SLOT8_2 = &S_CH[8].SLOT[SLOT2];
+ /* LFO state */
+ amsIncr = OPL->amsIncr;
+ vibIncr = OPL->vibIncr;
+ ams_table = OPL->ams_table;
+ vib_table = OPL->vib_table;
+ }
+ R_CH = rythm ? &S_CH[6] : E_CH;
+ for( i=0; i < length ; i++ )
+ {
+ /* channel A channel B channel C */
+ /* LFO */
+ ams = ams_table[(amsCnt+=amsIncr)>>AMS_SHIFT];
+ vib = vib_table[(vibCnt+=vibIncr)>>VIB_SHIFT];
+ outd[0] = 0;
+ /* FM part */
+ for(CH=S_CH ; CH < R_CH ; CH++)
+ OPL_CALC_CH(CH);
+ /* Rythn part */
+ if(rythm)
+ OPL_CALC_RH(S_CH);
+ /* limit check */
+ data = Limit( outd[0] , OPL_MAXOUT, OPL_MINOUT );
+ /* store to sound buffer */
+ buf[i] = data >> OPL_OUTSB;
+ }
+
+ OPL->amsCnt = amsCnt;
+ OPL->vibCnt = vibCnt;
+#ifdef OPL_OUTPUT_LOG
+ if(opl_dbg_fp)
+ {
+ for(opl_dbg_chip=0;opl_dbg_chip<opl_dbg_maxchip;opl_dbg_chip++)
+ if( opl_dbg_opl[opl_dbg_chip] == OPL) break;
+ fprintf(opl_dbg_fp,"%c%c%c",0x20+opl_dbg_chip,length&0xff,length/256);
+ }
+#endif
+}
+#endif /* (BUILD_YM3812 || BUILD_YM3526) */
+
+#if BUILD_Y8950
+
+void Y8950UpdateOne(FM_OPL *OPL, INT16 *buffer, int length)
+{
+ int i;
+ int data;
+ OPLSAMPLE *buf = buffer;
+ UINT32 amsCnt = OPL->amsCnt;
+ UINT32 vibCnt = OPL->vibCnt;
+ UINT8 rythm = OPL->rythm&0x20;
+ OPL_CH *CH,*R_CH;
+ YM_DELTAT *DELTAT = OPL->deltat;
+
+ /* setup DELTA-T unit */
+ YM_DELTAT_DECODE_PRESET(DELTAT);
+
+ if( (void *)OPL != cur_chip ){
+ cur_chip = (void *)OPL;
+ /* channel pointers */
+ S_CH = OPL->P_CH;
+ E_CH = &S_CH[9];
+ /* rythm slot */
+ SLOT7_1 = &S_CH[7].SLOT[SLOT1];
+ SLOT7_2 = &S_CH[7].SLOT[SLOT2];
+ SLOT8_1 = &S_CH[8].SLOT[SLOT1];
+ SLOT8_2 = &S_CH[8].SLOT[SLOT2];
+ /* LFO state */
+ amsIncr = OPL->amsIncr;
+ vibIncr = OPL->vibIncr;
+ ams_table = OPL->ams_table;
+ vib_table = OPL->vib_table;
+ }
+ R_CH = rythm ? &S_CH[6] : E_CH;
+ for( i=0; i < length ; i++ )
+ {
+ /* channel A channel B channel C */
+ /* LFO */
+ ams = ams_table[(amsCnt+=amsIncr)>>AMS_SHIFT];
+ vib = vib_table[(vibCnt+=vibIncr)>>VIB_SHIFT];
+ outd[0] = 0;
+ /* deltaT ADPCM */
+ if( DELTAT->portstate )
+ YM_DELTAT_ADPCM_CALC(DELTAT);
+ /* FM part */
+ for(CH=S_CH ; CH < R_CH ; CH++)
+ OPL_CALC_CH(CH);
+ /* Rythn part */
+ if(rythm)
+ OPL_CALC_RH(S_CH);
+ /* limit check */
+ data = Limit( outd[0] , OPL_MAXOUT, OPL_MINOUT );
+ /* store to sound buffer */
+ buf[i] = data >> OPL_OUTSB;
+ }
+ OPL->amsCnt = amsCnt;
+ OPL->vibCnt = vibCnt;
+ /* deltaT START flag */
+ if( !DELTAT->portstate )
+ OPL->status &= 0xfe;
+}
+#endif
+
+/* ---------- reset one of chip ---------- */
+void OPLResetChip(FM_OPL *OPL)
+{
+ int c,s;
+ int i;
+
+ /* reset chip */
+ OPL->mode = 0; /* normal mode */
+ OPL_STATUS_RESET(OPL,0x7f);
+ /* reset with register write */
+ OPLWriteReg(OPL,0x01,0); /* wabesel disable */
+ OPLWriteReg(OPL,0x02,0); /* Timer1 */
+ OPLWriteReg(OPL,0x03,0); /* Timer2 */
+ OPLWriteReg(OPL,0x04,0); /* IRQ mask clear */
+ for(i = 0xff ; i >= 0x20 ; i-- ) OPLWriteReg(OPL,i,0);
+ /* reset OPerator paramater */
+ for( c = 0 ; c < OPL->max_ch ; c++ )
+ {
+ OPL_CH *CH = &OPL->P_CH[c];
+ /* OPL->P_CH[c].PAN = OPN_CENTER; */
+ for(s = 0 ; s < 2 ; s++ )
+ {
+ /* wave table */
+ CH->SLOT[s].wavetable = &SIN_TABLE[0];
+ /* CH->SLOT[s].evm = ENV_MOD_RR; */
+ CH->SLOT[s].evc = EG_OFF;
+ CH->SLOT[s].eve = EG_OFF+1;
+ CH->SLOT[s].evs = 0;
+ }
+ }
+#if BUILD_Y8950
+ if(OPL->type&OPL_TYPE_ADPCM)
+ {
+ YM_DELTAT *DELTAT = OPL->deltat;
+
+ DELTAT->freqbase = OPL->freqbase;
+ DELTAT->output_pointer = outd;
+ DELTAT->portshift = 5;
+ DELTAT->output_range = DELTAT_MIXING_LEVEL<<TL_BITS;
+ YM_DELTAT_ADPCM_Reset(DELTAT,0);
+ }
+#endif
+}
+
+/* ---------- Create one of vietual YM3812 ---------- */
+/* 'rate' is sampling rate and 'bufsiz' is the size of the */
+FM_OPL *OPLCreate(int type, int clock, int rate)
+{
+ char *ptr;
+ FM_OPL *OPL;
+ int state_size;
+ int max_ch = 9; /* normaly 9 channels */
+
+ if( OPL_LockTable() ==-1) return NULL;
+ /* allocate OPL state space */
+ state_size = sizeof(FM_OPL);
+ state_size += sizeof(OPL_CH)*max_ch;
+#if BUILD_Y8950
+ if(type&OPL_TYPE_ADPCM) state_size+= sizeof(YM_DELTAT);
+#endif
+ /* allocate memory block */
+ ptr = malloc(state_size);
+ if(ptr==NULL) return NULL;
+ /* clear */
+ memset(ptr,0,state_size);
+ OPL = (FM_OPL *)ptr; ptr+=sizeof(FM_OPL);
+ OPL->P_CH = (OPL_CH *)ptr; ptr+=sizeof(OPL_CH)*max_ch;
+#if BUILD_Y8950
+ if(type&OPL_TYPE_ADPCM) OPL->deltat = (YM_DELTAT *)ptr; ptr+=sizeof(YM_DELTAT);
+#endif
+ /* set channel state pointer */
+ OPL->type = type;
+ OPL->clock = clock;
+ OPL->rate = rate;
+ OPL->max_ch = max_ch;
+ /* init grobal tables */
+ OPL_initalize(OPL);
+ /* reset chip */
+ OPLResetChip(OPL);
+#ifdef OPL_OUTPUT_LOG
+ if(!opl_dbg_fp)
+ {
+ opl_dbg_fp = fopen("opllog.opl","wb");
+ opl_dbg_maxchip = 0;
+ }
+ if(opl_dbg_fp)
+ {
+ opl_dbg_opl[opl_dbg_maxchip] = OPL;
+ fprintf(opl_dbg_fp,"%c%c%c%c%c%c",0x00+opl_dbg_maxchip,
+ type,
+ clock&0xff,
+ (clock/0x100)&0xff,
+ (clock/0x10000)&0xff,
+ (clock/0x1000000)&0xff);
+ opl_dbg_maxchip++;
+ }
+#endif
+ return OPL;
+}
+
+/* ---------- Destroy one of vietual YM3812 ---------- */
+void OPLDestroy(FM_OPL *OPL)
+{
+#ifdef OPL_OUTPUT_LOG
+ if(opl_dbg_fp)
+ {
+ fclose(opl_dbg_fp);
+ opl_dbg_fp = NULL;
+ }
+#endif
+ OPL_UnLockTable();
+ free(OPL);
+}
+
+/* ---------- Option handlers ---------- */
+
+void OPLSetTimerHandler(FM_OPL *OPL,OPL_TIMERHANDLER TimerHandler,int channelOffset)
+{
+ OPL->TimerHandler = TimerHandler;
+ OPL->TimerParam = channelOffset;
+}
+void OPLSetIRQHandler(FM_OPL *OPL,OPL_IRQHANDLER IRQHandler,int param)
+{
+ OPL->IRQHandler = IRQHandler;
+ OPL->IRQParam = param;
+}
+void OPLSetUpdateHandler(FM_OPL *OPL,OPL_UPDATEHANDLER UpdateHandler,int param)
+{
+ OPL->UpdateHandler = UpdateHandler;
+ OPL->UpdateParam = param;
+}
+#if BUILD_Y8950
+void OPLSetPortHandler(FM_OPL *OPL,OPL_PORTHANDLER_W PortHandler_w,OPL_PORTHANDLER_R PortHandler_r,int param)
+{
+ OPL->porthandler_w = PortHandler_w;
+ OPL->porthandler_r = PortHandler_r;
+ OPL->port_param = param;
+}
+
+void OPLSetKeyboardHandler(FM_OPL *OPL,OPL_PORTHANDLER_W KeyboardHandler_w,OPL_PORTHANDLER_R KeyboardHandler_r,int param)
+{
+ OPL->keyboardhandler_w = KeyboardHandler_w;
+ OPL->keyboardhandler_r = KeyboardHandler_r;
+ OPL->keyboard_param = param;
+}
+#endif
+/* ---------- YM3812 I/O interface ---------- */
+int OPLWrite(FM_OPL *OPL,int a,int v)
+{
+ if( !(a&1) )
+ { /* address port */
+ OPL->address = v & 0xff;
+ }
+ else
+ { /* data port */
+ if(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam,0);
+#ifdef OPL_OUTPUT_LOG
+ if(opl_dbg_fp)
+ {
+ for(opl_dbg_chip=0;opl_dbg_chip<opl_dbg_maxchip;opl_dbg_chip++)
+ if( opl_dbg_opl[opl_dbg_chip] == OPL) break;
+ fprintf(opl_dbg_fp,"%c%c%c",0x10+opl_dbg_chip,OPL->address,v);
+ }
+#endif
+ OPLWriteReg(OPL,OPL->address,v);
+ }
+ return OPL->status>>7;
+}
+
+unsigned char OPLRead(FM_OPL *OPL,int a)
+{
+ if( !(a&1) )
+ { /* status port */
+ return OPL->status & (OPL->statusmask|0x80);
+ }
+ /* data port */
+ switch(OPL->address)
+ {
+ case 0x05: /* KeyBoard IN */
+ if(OPL->type&OPL_TYPE_KEYBOARD)
+ {
+ if(OPL->keyboardhandler_r)
+ return OPL->keyboardhandler_r(OPL->keyboard_param);
+ else
+ LOG(LOG_WAR,("OPL:read unmapped KEYBOARD port\n"));
+ }
+ return 0;
+#if 0
+ case 0x0f: /* ADPCM-DATA */
+ return 0;
+#endif
+ case 0x19: /* I/O DATA */
+ if(OPL->type&OPL_TYPE_IO)
+ {
+ if(OPL->porthandler_r)
+ return OPL->porthandler_r(OPL->port_param);
+ else
+ LOG(LOG_WAR,("OPL:read unmapped I/O port\n"));
+ }
+ return 0;
+ case 0x1a: /* PCM-DATA */
+ return 0;
+ }
+ return 0;
+}
+
+int OPLTimerOver(FM_OPL *OPL,int c)
+{
+ if( c )
+ { /* Timer B */
+ OPL_STATUS_SET(OPL,0x20);
+ }
+ else
+ { /* Timer A */
+ OPL_STATUS_SET(OPL,0x40);
+ /* CSM mode key,TL controll */
+ if( OPL->mode & 0x80 )
+ { /* CSM mode total level latch and auto key on */
+ int ch;
+ if(OPL->UpdateHandler) OPL->UpdateHandler(OPL->UpdateParam,0);
+ for(ch=0;ch<9;ch++)
+ CSMKeyControll( &OPL->P_CH[ch] );
+ }
+ }
+ /* reload timer */
+ if (OPL->TimerHandler) (OPL->TimerHandler)(OPL->TimerParam+c,(double)OPL->T[c]*OPL->TimerBase);
+ return OPL->status>>7;
+}
--- /dev/null
+#ifndef __FMOPL_H_
+#define __FMOPL_H_
+
+/* --- select emulation chips --- */
+#define BUILD_YM3812 (HAS_YM3812)
+//#define BUILD_YM3526 (HAS_YM3526)
+//#define BUILD_Y8950 (HAS_Y8950)
+
+/* --- system optimize --- */
+/* select bit size of output : 8 or 16 */
+#define OPL_OUTPUT_BIT 16
+
+/* compiler dependence */
+#ifndef OSD_CPU_H
+#define OSD_CPU_H
+typedef unsigned char UINT8; /* unsigned 8bit */
+typedef unsigned short UINT16; /* unsigned 16bit */
+typedef unsigned int UINT32; /* unsigned 32bit */
+typedef signed char INT8; /* signed 8bit */
+typedef signed short INT16; /* signed 16bit */
+typedef signed int INT32; /* signed 32bit */
+#endif
+
+#if (OPL_OUTPUT_BIT==16)
+typedef INT16 OPLSAMPLE;
+#endif
+#if (OPL_OUTPUT_BIT==8)
+typedef unsigned char OPLSAMPLE;
+#endif
+
+
+#if BUILD_Y8950
+#include "ymdeltat.h"
+#endif
+
+typedef void (*OPL_TIMERHANDLER)(int channel,double interval_Sec);
+typedef void (*OPL_IRQHANDLER)(int param,int irq);
+typedef void (*OPL_UPDATEHANDLER)(int param,int min_interval_us);
+typedef void (*OPL_PORTHANDLER_W)(int param,unsigned char data);
+typedef unsigned char (*OPL_PORTHANDLER_R)(int param);
+
+/* !!!!! here is private section , do not access there member direct !!!!! */
+
+#define OPL_TYPE_WAVESEL 0x01 /* waveform select */
+#define OPL_TYPE_ADPCM 0x02 /* DELTA-T ADPCM unit */
+#define OPL_TYPE_KEYBOARD 0x04 /* keyboard interface */
+#define OPL_TYPE_IO 0x08 /* I/O port */
+
+/* Saving is necessary for member of the 'R' mark for suspend/resume */
+/* ---------- OPL one of slot ---------- */
+typedef struct fm_opl_slot {
+ INT32 TL; /* total level :TL << 8 */
+ INT32 TLL; /* adjusted now TL */
+ UINT8 KSR; /* key scale rate :(shift down bit) */
+ INT32 *AR; /* attack rate :&AR_TABLE[AR<<2] */
+ INT32 *DR; /* decay rate :&DR_TALBE[DR<<2] */
+ INT32 SL; /* sustin level :SL_TALBE[SL] */
+ INT32 *RR; /* release rate :&DR_TABLE[RR<<2] */
+ UINT8 ksl; /* keyscale level :(shift down bits) */
+ UINT8 ksr; /* key scale rate :kcode>>KSR */
+ UINT32 mul; /* multiple :ML_TABLE[ML] */
+ UINT32 Cnt; /* frequency count : */
+ UINT32 Incr; /* frequency step : */
+ /* envelope generator state */
+ UINT8 eg_typ; /* envelope type flag */
+ UINT8 evm; /* envelope phase */
+ INT32 evc; /* envelope counter */
+ INT32 eve; /* envelope counter end point */
+ INT32 evs; /* envelope counter step */
+ INT32 evsa; /* envelope step for AR :AR[ksr] */
+ INT32 evsd; /* envelope step for DR :DR[ksr] */
+ INT32 evsr; /* envelope step for RR :RR[ksr] */
+ /* LFO */
+ UINT8 ams; /* ams flag */
+ UINT8 vib; /* vibrate flag */
+ /* wave selector */
+ INT32 **wavetable;
+}OPL_SLOT;
+
+/* ---------- OPL one of channel ---------- */
+typedef struct fm_opl_channel {
+ OPL_SLOT SLOT[2];
+ UINT8 CON; /* connection type */
+ UINT8 FB; /* feed back :(shift down bit) */
+ INT32 *connect1; /* slot1 output pointer */
+ INT32 *connect2; /* slot2 output pointer */
+ INT32 op1_out[2]; /* slot1 output for selfeedback */
+ /* phase generator state */
+ UINT32 block_fnum; /* block+fnum : */
+ UINT8 kcode; /* key code : KeyScaleCode */
+ UINT32 fc; /* Freq. Increment base */
+ UINT32 ksl_base; /* KeyScaleLevel Base step */
+ UINT8 keyon; /* key on/off flag */
+} OPL_CH;
+
+/* OPL state */
+typedef struct fm_opl_f {
+ UINT8 type; /* chip type */
+ int clock; /* master clock (Hz) */
+ int rate; /* sampling rate (Hz) */
+ double freqbase; /* frequency base */
+ double TimerBase; /* Timer base time (==sampling time) */
+ UINT8 address; /* address register */
+ UINT8 status; /* status flag */
+ UINT8 statusmask; /* status mask */
+ UINT32 mode; /* Reg.08 : CSM , notesel,etc. */
+ /* Timer */
+ int T[2]; /* timer counter */
+ UINT8 st[2]; /* timer enable */
+ /* FM channel slots */
+ OPL_CH *P_CH; /* pointer of CH */
+ int max_ch; /* maximum channel */
+ /* Rythm sention */
+ UINT8 rythm; /* Rythm mode , key flag */
+#if BUILD_Y8950
+ /* Delta-T ADPCM unit (Y8950) */
+ YM_DELTAT *deltat; /* DELTA-T ADPCM */
+#endif
+ /* Keyboard / I/O interface unit (Y8950) */
+ UINT8 portDirection;
+ UINT8 portLatch;
+ OPL_PORTHANDLER_R porthandler_r;
+ OPL_PORTHANDLER_W porthandler_w;
+ int port_param;
+ OPL_PORTHANDLER_R keyboardhandler_r;
+ OPL_PORTHANDLER_W keyboardhandler_w;
+ int keyboard_param;
+ /* time tables */
+ INT32 AR_TABLE[75]; /* atttack rate tables */
+ INT32 DR_TABLE[75]; /* decay rate tables */
+ UINT32 FN_TABLE[1024]; /* fnumber -> increment counter */
+ /* LFO */
+ INT32 *ams_table;
+ INT32 *vib_table;
+ INT32 amsCnt;
+ INT32 amsIncr;
+ INT32 vibCnt;
+ INT32 vibIncr;
+ /* wave selector enable flag */
+ UINT8 wavesel;
+ /* external event callback handler */
+ OPL_TIMERHANDLER TimerHandler; /* TIMER handler */
+ int TimerParam; /* TIMER parameter */
+ OPL_IRQHANDLER IRQHandler; /* IRQ handler */
+ int IRQParam; /* IRQ parameter */
+ OPL_UPDATEHANDLER UpdateHandler; /* stream update handler */
+ int UpdateParam; /* stream update parameter */
+} FM_OPL;
+
+/* ---------- Generic interface section ---------- */
+#define OPL_TYPE_YM3526 (0)
+#define OPL_TYPE_YM3812 (OPL_TYPE_WAVESEL)
+#define OPL_TYPE_Y8950 (OPL_TYPE_ADPCM|OPL_TYPE_KEYBOARD|OPL_TYPE_IO)
+
+FM_OPL *OPLCreate(int type, int clock, int rate);
+void OPLDestroy(FM_OPL *OPL);
+void OPLSetTimerHandler(FM_OPL *OPL,OPL_TIMERHANDLER TimerHandler,int channelOffset);
+void OPLSetIRQHandler(FM_OPL *OPL,OPL_IRQHANDLER IRQHandler,int param);
+void OPLSetUpdateHandler(FM_OPL *OPL,OPL_UPDATEHANDLER UpdateHandler,int param);
+/* Y8950 port handlers */
+void OPLSetPortHandler(FM_OPL *OPL,OPL_PORTHANDLER_W PortHandler_w,OPL_PORTHANDLER_R PortHandler_r,int param);
+void OPLSetKeyboardHandler(FM_OPL *OPL,OPL_PORTHANDLER_W KeyboardHandler_w,OPL_PORTHANDLER_R KeyboardHandler_r,int param);
+
+void OPLResetChip(FM_OPL *OPL);
+int OPLWrite(FM_OPL *OPL,int a,int v);
+unsigned char OPLRead(FM_OPL *OPL,int a);
+int OPLTimerOver(FM_OPL *OPL,int c);
+
+/* YM3626/YM3812 local section */
+void YM3812UpdateOne(FM_OPL *OPL, INT16 *buffer, int length);
+
+void Y8950UpdateOne(FM_OPL *OPL, INT16 *buffer, int length);
+
+#endif
--- /dev/null
+/*
+ * QEMU 8253/8254 interval timer emulation
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+#include "xc.h"
+#include <io/ioreq.h>
+
+//#define DEBUG_PIT
+
+#define RW_STATE_LSB 1
+#define RW_STATE_MSB 2
+#define RW_STATE_WORD0 3
+#define RW_STATE_WORD1 4
+
+typedef struct PITChannelState {
+ int count; /* can be 65536 */
+ uint16_t latched_count;
+ uint8_t count_latched;
+ uint8_t status_latched;
+ uint8_t status;
+ uint8_t read_state;
+ uint8_t write_state;
+ uint8_t write_latch;
+ uint8_t rw_mode;
+ uint8_t mode;
+ uint8_t bcd; /* not supported */
+ uint8_t gate; /* timer start */
+ int64_t count_load_time;
+ /* irq handling */
+ int64_t next_transition_time;
+ QEMUTimer *irq_timer;
+ int irq;
+} PITChannelState;
+
+struct PITState {
+ PITChannelState channels[3];
+};
+
+static PITState pit_state;
+
+static void pit_irq_timer_update(PITChannelState *s, int64_t current_time);
+
+/* currently operate which channel for vmx use */
+int vmx_channel = -1;
+extern FILE *logfile;
+static int pit_get_count(PITChannelState *s)
+{
+ uint64_t d;
+ int counter;
+
+ d = muldiv64(qemu_get_clock(vm_clock) - s->count_load_time, PIT_FREQ, ticks_per_sec);
+ switch(s->mode) {
+ case 0:
+ case 1:
+ case 4:
+ case 5:
+ counter = (s->count - d) & 0xffff;
+ break;
+ case 3:
+ /* XXX: may be incorrect for odd counts */
+ counter = s->count - ((2 * d) % s->count);
+ break;
+ default:
+ counter = s->count - (d % s->count);
+ break;
+ }
+ return counter;
+}
+
+/* get pit output bit */
+static int pit_get_out1(PITChannelState *s, int64_t current_time)
+{
+ uint64_t d;
+ int out;
+
+ d = muldiv64(current_time - s->count_load_time, PIT_FREQ, ticks_per_sec);
+ switch(s->mode) {
+ default:
+ case 0:
+ out = (d >= s->count);
+ break;
+ case 1:
+ out = (d < s->count);
+ break;
+ case 2:
+ if ((d % s->count) == 0 && d != 0)
+ out = 1;
+ else
+ out = 0;
+ break;
+ case 3:
+ out = (d % s->count) < ((s->count + 1) >> 1);
+ break;
+ case 4:
+ case 5:
+ out = (d == s->count);
+ break;
+ }
+ return out;
+}
+
+int pit_get_out(PITState *pit, int channel, int64_t current_time)
+{
+ PITChannelState *s = &pit->channels[channel];
+ return pit_get_out1(s, current_time);
+}
+
+/* return -1 if no transition will occur. */
+static int64_t pit_get_next_transition_time(PITChannelState *s,
+ int64_t current_time)
+{
+ uint64_t d, next_time, base;
+ int period2;
+
+ d = muldiv64(current_time - s->count_load_time, PIT_FREQ, ticks_per_sec);
+ switch(s->mode) {
+ default:
+ case 0:
+ case 1:
+ if (d < s->count)
+ next_time = s->count;
+ else
+ return -1;
+ break;
+ case 2:
+ base = (d / s->count) * s->count;
+ if ((d - base) == 0 && d != 0)
+ next_time = base + s->count;
+ else
+ next_time = base + s->count + 1;
+ break;
+ case 3:
+ base = (d / s->count) * s->count;
+ period2 = ((s->count + 1) >> 1);
+ if ((d - base) < period2)
+ next_time = base + period2;
+ else
+ next_time = base + s->count;
+ break;
+ case 4:
+ case 5:
+ if (d < s->count)
+ next_time = s->count;
+ else if (d == s->count)
+ next_time = s->count + 1;
+ else
+ return -1;
+ break;
+ }
+ /* convert to timer units */
+ next_time = s->count_load_time + muldiv64(next_time, ticks_per_sec, PIT_FREQ);
+ /* fix potential rounding problems */
+ /* XXX: better solution: use a clock at PIT_FREQ Hz */
+ if (next_time <= current_time)
+ next_time = current_time + 1;
+ return next_time;
+}
+
+/* val must be 0 or 1 */
+void pit_set_gate(PITState *pit, int channel, int val)
+{
+ PITChannelState *s = &pit->channels[channel];
+
+ switch(s->mode) {
+ default:
+ case 0:
+ case 4:
+ /* XXX: just disable/enable counting */
+ break;
+ case 1:
+ case 5:
+ if (s->gate < val) {
+ /* restart counting on rising edge */
+ s->count_load_time = qemu_get_clock(vm_clock);
+ pit_irq_timer_update(s, s->count_load_time);
+ }
+ break;
+ case 2:
+ case 3:
+ if (s->gate < val) {
+ /* restart counting on rising edge */
+ s->count_load_time = qemu_get_clock(vm_clock);
+ pit_irq_timer_update(s, s->count_load_time);
+ }
+ /* XXX: disable/enable counting */
+ break;
+ }
+ s->gate = val;
+}
+
+int pit_get_gate(PITState *pit, int channel)
+{
+ PITChannelState *s = &pit->channels[channel];
+ return s->gate;
+}
+
+static inline void pit_load_count(PITChannelState *s, int val)
+{
+ extern void *shared_page;
+ ioreq_t *req;
+ int irq;
+
+ if (val == 0)
+ val = 0x10000;
+ s->count_load_time = qemu_get_clock(vm_clock);
+ s->count = val;
+
+ /* guest init this pit channel for periodic mode. we do not update related
+ * timer so the channel never send intr from device model*/
+ if (vmx_channel != -1 && s->mode == 2) {
+ /* get the pit irq(0)'s vector from pic DM */
+ if ((irq = pic_irq2vec(0)) >= 0) {
+ fprintf(logfile,
+ "VMX_PIT:guest init pit channel %d!\n", vmx_channel);
+ req = &((vcpu_iodata_t *) shared_page)->vp_ioreq;
+
+ req->state = STATE_IORESP_HOOK;
+ /*
+ * info passed to HV as following
+ * -- init count:16 bit, timer vec:8 bit,
+ * PIT channel(0~2):2 bit, rw mode:2 bit
+ */
+ req->u.data = s->count;
+ req->u.data |= (irq << 16);
+ req->u.data |= (vmx_channel << 24);
+ req->u.data |= ((s->rw_mode) << 26);
+ fprintf(logfile, "VMX_PIT:pass info 0x%llx to HV!\n", req->u.data);
+ vmx_channel = -1;
+ }
+ }
+
+/* pit_irq_timer_update(s, s->count_load_time);*/
+}
+
+/* if already latched, do not latch again */
+static void pit_latch_count(PITChannelState *s)
+{
+ if (!s->count_latched) {
+ s->latched_count = pit_get_count(s);
+ s->count_latched = s->rw_mode;
+ }
+}
+
+static void pit_ioport_write(void *opaque, uint32_t addr, uint32_t val)
+{
+ PITState *pit = opaque;
+ int channel, access;
+ PITChannelState *s;
+
+ addr &= 3;
+ if (addr == 3) {
+ channel = val >> 6;
+ if (channel == 3) {
+ /* read back command */
+ for(channel = 0; channel < 3; channel++) {
+ s = &pit->channels[channel];
+ if (val & (2 << channel)) {
+ if (!(val & 0x20)) {
+ pit_latch_count(s);
+ }
+ if (!(val & 0x10) && !s->status_latched) {
+ /* status latch */
+ /* XXX: add BCD and null count */
+ s->status = (pit_get_out1(s, qemu_get_clock(vm_clock)) << 7) |
+ (s->rw_mode << 4) |
+ (s->mode << 1) |
+ s->bcd;
+ s->status_latched = 1;
+ }
+ }
+ }
+ } else {
+ s = &pit->channels[channel];
+ access = (val >> 4) & 3;
+ if (access == 0) {
+ pit_latch_count(s);
+ } else {
+ s->rw_mode = access;
+ s->read_state = access;
+ s->write_state = access;
+
+ s->mode = (val >> 1) & 7;
+ s->bcd = val & 1;
+ /* XXX: update irq timer ? */
+ }
+ }
+ } else {
+ s = &pit->channels[addr];
+ vmx_channel = addr;
+ switch(s->write_state) {
+ default:
+ case RW_STATE_LSB:
+ pit_load_count(s, val);
+ break;
+ case RW_STATE_MSB:
+ pit_load_count(s, val << 8);
+ break;
+ case RW_STATE_WORD0:
+ s->write_latch = val;
+ s->write_state = RW_STATE_WORD1;
+ break;
+ case RW_STATE_WORD1:
+ pit_load_count(s, s->write_latch | (val << 8));
+ s->write_state = RW_STATE_WORD0;
+ break;
+ }
+ }
+}
+
+static uint32_t pit_ioport_read(void *opaque, uint32_t addr)
+{
+ PITState *pit = opaque;
+ int ret, count;
+ PITChannelState *s;
+
+ addr &= 3;
+ s = &pit->channels[addr];
+ if (s->status_latched) {
+ s->status_latched = 0;
+ ret = s->status;
+ } else if (s->count_latched) {
+ switch(s->count_latched) {
+ default:
+ case RW_STATE_LSB:
+ ret = s->latched_count & 0xff;
+ s->count_latched = 0;
+ break;
+ case RW_STATE_MSB:
+ ret = s->latched_count >> 8;
+ s->count_latched = 0;
+ break;
+ case RW_STATE_WORD0:
+ ret = s->latched_count & 0xff;
+ s->count_latched = RW_STATE_MSB;
+ break;
+ }
+ } else {
+ switch(s->read_state) {
+ default:
+ case RW_STATE_LSB:
+ count = pit_get_count(s);
+ ret = count & 0xff;
+ break;
+ case RW_STATE_MSB:
+ count = pit_get_count(s);
+ ret = (count >> 8) & 0xff;
+ break;
+ case RW_STATE_WORD0:
+ count = pit_get_count(s);
+ ret = count & 0xff;
+ s->read_state = RW_STATE_WORD1;
+ break;
+ case RW_STATE_WORD1:
+ count = pit_get_count(s);
+ ret = (count >> 8) & 0xff;
+ s->read_state = RW_STATE_WORD0;
+ break;
+ }
+ }
+ return ret;
+}
+
+static void pit_irq_timer_update(PITChannelState *s, int64_t current_time)
+{
+ int64_t expire_time;
+ int irq_level;
+
+ if (!s->irq_timer)
+ return;
+ expire_time = pit_get_next_transition_time(s, current_time);
+ irq_level = pit_get_out1(s, current_time);
+ pic_set_irq(s->irq, irq_level);
+#ifdef DEBUG_PIT
+ printf("irq_level=%d next_delay=%f\n",
+ irq_level,
+ (double)(expire_time - current_time) / ticks_per_sec);
+#endif
+ s->next_transition_time = expire_time;
+ if (expire_time != -1)
+ qemu_mod_timer(s->irq_timer, expire_time);
+ else
+ qemu_del_timer(s->irq_timer);
+}
+
+static void pit_irq_timer(void *opaque)
+{
+ PITChannelState *s = opaque;
+
+ pit_irq_timer_update(s, s->next_transition_time);
+}
+
+static void pit_save(QEMUFile *f, void *opaque)
+{
+ PITState *pit = opaque;
+ PITChannelState *s;
+ int i;
+
+ for(i = 0; i < 3; i++) {
+ s = &pit->channels[i];
+ qemu_put_be32s(f, &s->count);
+ qemu_put_be16s(f, &s->latched_count);
+ qemu_put_8s(f, &s->count_latched);
+ qemu_put_8s(f, &s->status_latched);
+ qemu_put_8s(f, &s->status);
+ qemu_put_8s(f, &s->read_state);
+ qemu_put_8s(f, &s->write_state);
+ qemu_put_8s(f, &s->write_latch);
+ qemu_put_8s(f, &s->rw_mode);
+ qemu_put_8s(f, &s->mode);
+ qemu_put_8s(f, &s->bcd);
+ qemu_put_8s(f, &s->gate);
+ qemu_put_be64s(f, &s->count_load_time);
+ if (s->irq_timer) {
+ qemu_put_be64s(f, &s->next_transition_time);
+ qemu_put_timer(f, s->irq_timer);
+ }
+ }
+}
+
+static int pit_load(QEMUFile *f, void *opaque, int version_id)
+{
+ PITState *pit = opaque;
+ PITChannelState *s;
+ int i;
+
+ if (version_id != 1)
+ return -EINVAL;
+
+ for(i = 0; i < 3; i++) {
+ s = &pit->channels[i];
+ qemu_get_be32s(f, &s->count);
+ qemu_get_be16s(f, &s->latched_count);
+ qemu_get_8s(f, &s->count_latched);
+ qemu_get_8s(f, &s->status_latched);
+ qemu_get_8s(f, &s->status);
+ qemu_get_8s(f, &s->read_state);
+ qemu_get_8s(f, &s->write_state);
+ qemu_get_8s(f, &s->write_latch);
+ qemu_get_8s(f, &s->rw_mode);
+ qemu_get_8s(f, &s->mode);
+ qemu_get_8s(f, &s->bcd);
+ qemu_get_8s(f, &s->gate);
+ qemu_get_be64s(f, &s->count_load_time);
+ if (s->irq_timer) {
+ qemu_get_be64s(f, &s->next_transition_time);
+ qemu_get_timer(f, s->irq_timer);
+ }
+ }
+ return 0;
+}
+
+static void pit_reset(void *opaque)
+{
+ PITState *pit = opaque;
+ PITChannelState *s;
+ int i;
+
+ for(i = 0;i < 3; i++) {
+ s = &pit->channels[i];
+ s->mode = 3;
+ s->gate = (i != 2);
+ pit_load_count(s, 0);
+ }
+}
+
+PITState *pit_init(int base, int irq)
+{
+ PITState *pit = &pit_state;
+ PITChannelState *s;
+
+ s = &pit->channels[0];
+ /* the timer 0 is connected to an IRQ */
+ s->irq_timer = qemu_new_timer(vm_clock, pit_irq_timer, s);
+ s->irq = irq;
+
+ register_savevm("i8254", base, 1, pit_save, pit_load, pit);
+
+ qemu_register_reset(pit_reset, pit);
+ register_ioport_write(base, 4, 1, pit_ioport_write, pit);
+ register_ioport_read(base, 3, 1, pit_ioport_read, pit);
+
+ pit_reset(pit);
+
+ return pit;
+}
--- /dev/null
+/*
+ * QEMU 8259 interrupt controller emulation
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+
+/* debug PIC */
+//#define DEBUG_PIC
+
+//#define DEBUG_IRQ_LATENCY
+//#define DEBUG_IRQ_COUNT
+
+typedef struct PicState {
+ uint8_t last_irr; /* edge detection */
+ uint8_t irr; /* interrupt request register */
+ uint8_t imr; /* interrupt mask register */
+ uint8_t isr; /* interrupt service register */
+ uint8_t priority_add; /* highest irq priority */
+ uint8_t irq_base;
+ uint8_t read_reg_select;
+ uint8_t poll;
+ uint8_t special_mask;
+ uint8_t init_state;
+ uint8_t auto_eoi;
+ uint8_t rotate_on_auto_eoi;
+ uint8_t special_fully_nested_mode;
+ uint8_t init4; /* true if 4 byte init */
+ uint8_t elcr; /* PIIX edge/trigger selection*/
+ uint8_t elcr_mask;
+} PicState;
+
+/* 0 is master pic, 1 is slave pic */
+static PicState pics[2];
+
+#if defined(DEBUG_PIC) || defined (DEBUG_IRQ_COUNT)
+static int irq_level[16];
+#endif
+#ifdef DEBUG_IRQ_COUNT
+static uint64_t irq_count[16];
+#endif
+
+/* set irq level. If an edge is detected, then the IRR is set to 1 */
+static inline void pic_set_irq1(PicState *s, int irq, int level)
+{
+ int mask;
+ mask = 1 << irq;
+ if (s->elcr & mask) {
+ /* level triggered */
+ if (level) {
+ s->irr |= mask;
+ s->last_irr |= mask;
+ } else {
+ s->irr &= ~mask;
+ s->last_irr &= ~mask;
+ }
+ } else {
+ /* edge triggered */
+ if (level) {
+ if ((s->last_irr & mask) == 0)
+ s->irr |= mask;
+ s->last_irr |= mask;
+ } else {
+ s->last_irr &= ~mask;
+ }
+ }
+}
+
+/* return the highest priority found in mask (highest = smallest
+ number). Return 8 if no irq */
+static inline int get_priority(PicState *s, int mask)
+{
+ int priority;
+ if (mask == 0)
+ return 8;
+ priority = 0;
+ while ((mask & (1 << ((priority + s->priority_add) & 7))) == 0)
+ priority++;
+ return priority;
+}
+
+/* return the pic wanted interrupt. return -1 if none */
+static int pic_get_irq(PicState *s)
+{
+ int mask, cur_priority, priority;
+
+ mask = s->irr & ~s->imr;
+ priority = get_priority(s, mask);
+ if (priority == 8)
+ return -1;
+ /* compute current priority. If special fully nested mode on the
+ master, the IRQ coming from the slave is not taken into account
+ for the priority computation. */
+ mask = s->isr;
+ if (s->special_fully_nested_mode && s == &pics[0])
+ mask &= ~(1 << 2);
+ cur_priority = get_priority(s, mask);
+ if (priority < cur_priority) {
+ /* higher priority found: an irq should be generated */
+ return (priority + s->priority_add) & 7;
+ } else {
+ return -1;
+ }
+}
+
+/* raise irq to CPU if necessary. must be called every time the active
+ irq may change */
+static void pic_update_irq(void)
+{
+ int irq2, irq;
+
+ /* first look at slave pic */
+ irq2 = pic_get_irq(&pics[1]);
+ if (irq2 >= 0) {
+ /* if irq request by slave pic, signal master PIC */
+ pic_set_irq1(&pics[0], 2, 1);
+ pic_set_irq1(&pics[0], 2, 0);
+ }
+ /* look at requested irq */
+ irq = pic_get_irq(&pics[0]);
+ if (irq >= 0) {
+#if defined(DEBUG_PIC)
+ {
+ int i;
+ for(i = 0; i < 2; i++) {
+ printf("pic%d: imr=%x irr=%x padd=%d\n",
+ i, pics[i].imr, pics[i].irr, pics[i].priority_add);
+
+ }
+ }
+ printf("pic: cpu_interrupt\n");
+#endif
+ cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HARD);
+ }
+}
+
+#ifdef DEBUG_IRQ_LATENCY
+int64_t irq_time[16];
+#endif
+
+void pic_set_irq(int irq, int level)
+{
+#if defined(DEBUG_PIC) || defined(DEBUG_IRQ_COUNT)
+ if (level != irq_level[irq]) {
+#if defined(DEBUG_PIC)
+ printf("pic_set_irq: irq=%d level=%d\n", irq, level);
+#endif
+ irq_level[irq] = level;
+#ifdef DEBUG_IRQ_COUNT
+ if (level == 1)
+ irq_count[irq]++;
+#endif
+ }
+#endif
+#ifdef DEBUG_IRQ_LATENCY
+ if (level) {
+ irq_time[irq] = qemu_get_clock(vm_clock);
+ }
+#endif
+ pic_set_irq1(&pics[irq >> 3], irq & 7, level);
+ pic_update_irq();
+}
+
+/* acknowledge interrupt 'irq' */
+static inline void pic_intack(PicState *s, int irq)
+{
+ if (s->auto_eoi) {
+ if (s->rotate_on_auto_eoi)
+ s->priority_add = (irq + 1) & 7;
+ } else {
+ s->isr |= (1 << irq);
+ }
+ /* We don't clear a level sensitive interrupt here */
+ if (!(s->elcr & (1 << irq)))
+ s->irr &= ~(1 << irq);
+}
+
+int cpu_get_pic_interrupt(CPUState *env)
+{
+ int irq, irq2, intno;
+
+ /* read the irq from the PIC */
+
+ irq = pic_get_irq(&pics[0]);
+ if (irq >= 0) {
+ pic_intack(&pics[0], irq);
+ if (irq == 2) {
+ irq2 = pic_get_irq(&pics[1]);
+ if (irq2 >= 0) {
+ pic_intack(&pics[1], irq2);
+ } else {
+ /* spurious IRQ on slave controller */
+ irq2 = 7;
+ }
+ intno = pics[1].irq_base + irq2;
+ irq = irq2 + 8;
+ } else {
+ intno = pics[0].irq_base + irq;
+ }
+ } else {
+ /* spurious IRQ on host controller */
+ irq = 7;
+ intno = pics[0].irq_base + irq;
+ }
+ pic_update_irq();
+
+#ifdef DEBUG_IRQ_LATENCY
+ printf("IRQ%d latency=%0.3fus\n",
+ irq,
+ (double)(qemu_get_clock(vm_clock) - irq_time[irq]) * 1000000.0 / ticks_per_sec);
+#endif
+#if defined(DEBUG_PIC)
+ printf("pic_interrupt: irq=%d\n", irq);
+#endif
+ return intno;
+}
+
+int pic_irq2vec(int irq)
+{
+ int vector = -1;
+
+ if (irq >= 8 && irq <= 15) {
+ if (pics[1].irq_base != 0xFF)
+ vector = pics[1].irq_base + irq;
+ } else if (irq != 2 && irq <= 7) {
+ if (pics[0].irq_base != 0xFF)
+ vector = pics[0].irq_base + irq;
+ }
+ return vector;
+}
+
+static void pic_reset(void *opaque)
+{
+ PicState *s = opaque;
+ int tmp;
+
+ tmp = s->elcr_mask;
+ memset(s, 0, sizeof(PicState));
+ s->elcr_mask = tmp;
+}
+
+static void pic_ioport_write(void *opaque, uint32_t addr, uint32_t val)
+{
+ PicState *s = opaque;
+ int priority, cmd, irq;
+
+#ifdef DEBUG_PIC
+ printf("pic_write: addr=0x%02x val=0x%02x\n", addr, val);
+#endif
+ addr &= 1;
+ if (addr == 0) {
+ if (val & 0x10) {
+ /* init */
+ pic_reset(s);
+ /* deassert a pending interrupt */
+ cpu_reset_interrupt(cpu_single_env, CPU_INTERRUPT_HARD);
+
+ s->init_state = 1;
+ s->init4 = val & 1;
+ if (val & 0x02)
+ hw_error("single mode not supported");
+ if (val & 0x08)
+ hw_error("level sensitive irq not supported");
+ } else if (val & 0x08) {
+ if (val & 0x04)
+ s->poll = 1;
+ if (val & 0x02)
+ s->read_reg_select = val & 1;
+ if (val & 0x40)
+ s->special_mask = (val >> 5) & 1;
+ } else {
+ cmd = val >> 5;
+ switch(cmd) {
+ case 0:
+ case 4:
+ s->rotate_on_auto_eoi = cmd >> 2;
+ break;
+ case 1: /* end of interrupt */
+ case 5:
+ priority = get_priority(s, s->isr);
+ if (priority != 8) {
+ irq = (priority + s->priority_add) & 7;
+ s->isr &= ~(1 << irq);
+ if (cmd == 5)
+ s->priority_add = (irq + 1) & 7;
+ pic_update_irq();
+ }
+ break;
+ case 3:
+ irq = val & 7;
+ s->isr &= ~(1 << irq);
+ pic_update_irq();
+ break;
+ case 6:
+ s->priority_add = (val + 1) & 7;
+ pic_update_irq();
+ break;
+ case 7:
+ irq = val & 7;
+ s->isr &= ~(1 << irq);
+ s->priority_add = (irq + 1) & 7;
+ pic_update_irq();
+ break;
+ default:
+ /* no operation */
+ break;
+ }
+ }
+ } else {
+ switch(s->init_state) {
+ case 0:
+ /* normal mode */
+ s->imr = val;
+ pic_update_irq();
+ break;
+ case 1:
+ s->irq_base = val & 0xf8;
+ s->init_state = 2;
+ break;
+ case 2:
+ if (s->init4) {
+ s->init_state = 3;
+ } else {
+ s->init_state = 0;
+ }
+ break;
+ case 3:
+ s->special_fully_nested_mode = (val >> 4) & 1;
+ s->auto_eoi = (val >> 1) & 1;
+ s->init_state = 0;
+ break;
+ }
+ }
+}
+
+static uint32_t pic_poll_read (PicState *s, uint32_t addr1)
+{
+ int ret;
+
+ ret = pic_get_irq(s);
+ if (ret >= 0) {
+ if (addr1 >> 7) {
+ pics[0].isr &= ~(1 << 2);
+ pics[0].irr &= ~(1 << 2);
+ }
+ s->irr &= ~(1 << ret);
+ s->isr &= ~(1 << ret);
+ if (addr1 >> 7 || ret != 2)
+ pic_update_irq();
+ } else {
+ ret = 0x07;
+ pic_update_irq();
+ }
+
+ return ret;
+}
+
+static uint32_t pic_ioport_read(void *opaque, uint32_t addr1)
+{
+ PicState *s = opaque;
+ unsigned int addr;
+ int ret;
+
+ addr = addr1;
+ addr &= 1;
+ if (s->poll) {
+ ret = pic_poll_read(s, addr1);
+ s->poll = 0;
+ } else {
+ if (addr == 0) {
+ if (s->read_reg_select)
+ ret = s->isr;
+ else
+ ret = s->irr;
+ } else {
+ ret = s->imr;
+ }
+ }
+#ifdef DEBUG_PIC
+ printf("pic_read: addr=0x%02x val=0x%02x\n", addr1, ret);
+#endif
+ return ret;
+}
+
+/* memory mapped interrupt status */
+uint32_t pic_intack_read(CPUState *env)
+{
+ int ret;
+
+ ret = pic_poll_read(&pics[0], 0x00);
+ if (ret == 2)
+ ret = pic_poll_read(&pics[1], 0x80) + 8;
+ /* Prepare for ISR read */
+ pics[0].read_reg_select = 1;
+
+ return ret;
+}
+
+static void elcr_ioport_write(void *opaque, uint32_t addr, uint32_t val)
+{
+ PicState *s = opaque;
+ s->elcr = val & s->elcr_mask;
+}
+
+static uint32_t elcr_ioport_read(void *opaque, uint32_t addr1)
+{
+ PicState *s = opaque;
+ return s->elcr;
+}
+
+static void pic_save(QEMUFile *f, void *opaque)
+{
+ PicState *s = opaque;
+
+ qemu_put_8s(f, &s->last_irr);
+ qemu_put_8s(f, &s->irr);
+ qemu_put_8s(f, &s->imr);
+ qemu_put_8s(f, &s->isr);
+ qemu_put_8s(f, &s->priority_add);
+ qemu_put_8s(f, &s->irq_base);
+ qemu_put_8s(f, &s->read_reg_select);
+ qemu_put_8s(f, &s->poll);
+ qemu_put_8s(f, &s->special_mask);
+ qemu_put_8s(f, &s->init_state);
+ qemu_put_8s(f, &s->auto_eoi);
+ qemu_put_8s(f, &s->rotate_on_auto_eoi);
+ qemu_put_8s(f, &s->special_fully_nested_mode);
+ qemu_put_8s(f, &s->init4);
+ qemu_put_8s(f, &s->elcr);
+}
+
+static int pic_load(QEMUFile *f, void *opaque, int version_id)
+{
+ PicState *s = opaque;
+
+ if (version_id != 1)
+ return -EINVAL;
+
+ qemu_get_8s(f, &s->last_irr);
+ qemu_get_8s(f, &s->irr);
+ qemu_get_8s(f, &s->imr);
+ qemu_get_8s(f, &s->isr);
+ qemu_get_8s(f, &s->priority_add);
+ qemu_get_8s(f, &s->irq_base);
+ qemu_get_8s(f, &s->read_reg_select);
+ qemu_get_8s(f, &s->poll);
+ qemu_get_8s(f, &s->special_mask);
+ qemu_get_8s(f, &s->init_state);
+ qemu_get_8s(f, &s->auto_eoi);
+ qemu_get_8s(f, &s->rotate_on_auto_eoi);
+ qemu_get_8s(f, &s->special_fully_nested_mode);
+ qemu_get_8s(f, &s->init4);
+ qemu_get_8s(f, &s->elcr);
+ return 0;
+}
+
+/* XXX: add generic master/slave system */
+static void pic_init1(int io_addr, int elcr_addr, PicState *s)
+{
+ register_ioport_write(io_addr, 2, 1, pic_ioport_write, s);
+ register_ioport_read(io_addr, 2, 1, pic_ioport_read, s);
+ if (elcr_addr >= 0) {
+ register_ioport_write(elcr_addr, 1, 1, elcr_ioport_write, s);
+ register_ioport_read(elcr_addr, 1, 1, elcr_ioport_read, s);
+ }
+ register_savevm("i8259", io_addr, 1, pic_save, pic_load, s);
+ qemu_register_reset(pic_reset, s);
+}
+
+void pic_info(void)
+{
+ int i;
+ PicState *s;
+
+ for(i=0;i<2;i++) {
+ s = &pics[i];
+ term_printf("pic%d: irr=%02x imr=%02x isr=%02x hprio=%d irq_base=%02x rr_sel=%d elcr=%02x fnm=%d\n",
+ i, s->irr, s->imr, s->isr, s->priority_add,
+ s->irq_base, s->read_reg_select, s->elcr,
+ s->special_fully_nested_mode);
+ }
+}
+
+void irq_info(void)
+{
+#ifndef DEBUG_IRQ_COUNT
+ term_printf("irq statistic code not compiled.\n");
+#else
+ int i;
+ int64_t count;
+
+ term_printf("IRQ statistics:\n");
+ for (i = 0; i < 16; i++) {
+ count = irq_count[i];
+ if (count > 0)
+ term_printf("%2d: %lld\n", i, count);
+ }
+#endif
+}
+
+void pic_init(void)
+{
+ pic_init1(0x20, 0x4d0, &pics[0]);
+ pic_init1(0xa0, 0x4d1, &pics[1]);
+ pics[0].elcr_mask = 0xf8;
+ pics[1].elcr_mask = 0xde;
+ pics[0].irq_base = 0xff;
+ pics[0].irq_base = 0xff;
+}
+
--- /dev/null
+/*
+ * QEMU IDE disk and CD-ROM Emulator
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+
+/* debug IDE devices */
+//#define DEBUG_IDE
+//#define DEBUG_IDE_ATAPI
+
+/* Bits of HD_STATUS */
+#define ERR_STAT 0x01
+#define INDEX_STAT 0x02
+#define ECC_STAT 0x04 /* Corrected error */
+#define DRQ_STAT 0x08
+#define SEEK_STAT 0x10
+#define SRV_STAT 0x10
+#define WRERR_STAT 0x20
+#define READY_STAT 0x40
+#define BUSY_STAT 0x80
+
+/* Bits for HD_ERROR */
+#define MARK_ERR 0x01 /* Bad address mark */
+#define TRK0_ERR 0x02 /* couldn't find track 0 */
+#define ABRT_ERR 0x04 /* Command aborted */
+#define MCR_ERR 0x08 /* media change request */
+#define ID_ERR 0x10 /* ID field not found */
+#define MC_ERR 0x20 /* media changed */
+#define ECC_ERR 0x40 /* Uncorrectable ECC error */
+#define BBD_ERR 0x80 /* pre-EIDE meaning: block marked bad */
+#define ICRC_ERR 0x80 /* new meaning: CRC error during transfer */
+
+/* Bits of HD_NSECTOR */
+#define CD 0x01
+#define IO 0x02
+#define REL 0x04
+#define TAG_MASK 0xf8
+
+#define IDE_CMD_RESET 0x04
+#define IDE_CMD_DISABLE_IRQ 0x02
+
+/* ATA/ATAPI Commands pre T13 Spec */
+#define WIN_NOP 0x00
+/*
+ * 0x01->0x02 Reserved
+ */
+#define CFA_REQ_EXT_ERROR_CODE 0x03 /* CFA Request Extended Error Code */
+/*
+ * 0x04->0x07 Reserved
+ */
+#define WIN_SRST 0x08 /* ATAPI soft reset command */
+#define WIN_DEVICE_RESET 0x08
+/*
+ * 0x09->0x0F Reserved
+ */
+#define WIN_RECAL 0x10
+#define WIN_RESTORE WIN_RECAL
+/*
+ * 0x10->0x1F Reserved
+ */
+#define WIN_READ 0x20 /* 28-Bit */
+#define WIN_READ_ONCE 0x21 /* 28-Bit without retries */
+#define WIN_READ_LONG 0x22 /* 28-Bit */
+#define WIN_READ_LONG_ONCE 0x23 /* 28-Bit without retries */
+#define WIN_READ_EXT 0x24 /* 48-Bit */
+#define WIN_READDMA_EXT 0x25 /* 48-Bit */
+#define WIN_READDMA_QUEUED_EXT 0x26 /* 48-Bit */
+#define WIN_READ_NATIVE_MAX_EXT 0x27 /* 48-Bit */
+/*
+ * 0x28
+ */
+#define WIN_MULTREAD_EXT 0x29 /* 48-Bit */
+/*
+ * 0x2A->0x2F Reserved
+ */
+#define WIN_WRITE 0x30 /* 28-Bit */
+#define WIN_WRITE_ONCE 0x31 /* 28-Bit without retries */
+#define WIN_WRITE_LONG 0x32 /* 28-Bit */
+#define WIN_WRITE_LONG_ONCE 0x33 /* 28-Bit without retries */
+#define WIN_WRITE_EXT 0x34 /* 48-Bit */
+#define WIN_WRITEDMA_EXT 0x35 /* 48-Bit */
+#define WIN_WRITEDMA_QUEUED_EXT 0x36 /* 48-Bit */
+#define WIN_SET_MAX_EXT 0x37 /* 48-Bit */
+#define CFA_WRITE_SECT_WO_ERASE 0x38 /* CFA Write Sectors without erase */
+#define WIN_MULTWRITE_EXT 0x39 /* 48-Bit */
+/*
+ * 0x3A->0x3B Reserved
+ */
+#define WIN_WRITE_VERIFY 0x3C /* 28-Bit */
+/*
+ * 0x3D->0x3F Reserved
+ */
+#define WIN_VERIFY 0x40 /* 28-Bit - Read Verify Sectors */
+#define WIN_VERIFY_ONCE 0x41 /* 28-Bit - without retries */
+#define WIN_VERIFY_EXT 0x42 /* 48-Bit */
+/*
+ * 0x43->0x4F Reserved
+ */
+#define WIN_FORMAT 0x50
+/*
+ * 0x51->0x5F Reserved
+ */
+#define WIN_INIT 0x60
+/*
+ * 0x61->0x5F Reserved
+ */
+#define WIN_SEEK 0x70 /* 0x70-0x7F Reserved */
+#define CFA_TRANSLATE_SECTOR 0x87 /* CFA Translate Sector */
+#define WIN_DIAGNOSE 0x90
+#define WIN_SPECIFY 0x91 /* set drive geometry translation */
+#define WIN_DOWNLOAD_MICROCODE 0x92
+#define WIN_STANDBYNOW2 0x94
+#define WIN_STANDBY2 0x96
+#define WIN_SETIDLE2 0x97
+#define WIN_CHECKPOWERMODE2 0x98
+#define WIN_SLEEPNOW2 0x99
+/*
+ * 0x9A VENDOR
+ */
+#define WIN_PACKETCMD 0xA0 /* Send a packet command. */
+#define WIN_PIDENTIFY 0xA1 /* identify ATAPI device */
+#define WIN_QUEUED_SERVICE 0xA2
+#define WIN_SMART 0xB0 /* self-monitoring and reporting */
+#define CFA_ERASE_SECTORS 0xC0
+#define WIN_MULTREAD 0xC4 /* read sectors using multiple mode*/
+#define WIN_MULTWRITE 0xC5 /* write sectors using multiple mode */
+#define WIN_SETMULT 0xC6 /* enable/disable multiple mode */
+#define WIN_READDMA_QUEUED 0xC7 /* read sectors using Queued DMA transfers */
+#define WIN_READDMA 0xC8 /* read sectors using DMA transfers */
+#define WIN_READDMA_ONCE 0xC9 /* 28-Bit - without retries */
+#define WIN_WRITEDMA 0xCA /* write sectors using DMA transfers */
+#define WIN_WRITEDMA_ONCE 0xCB /* 28-Bit - without retries */
+#define WIN_WRITEDMA_QUEUED 0xCC /* write sectors using Queued DMA transfers */
+#define CFA_WRITE_MULTI_WO_ERASE 0xCD /* CFA Write multiple without erase */
+#define WIN_GETMEDIASTATUS 0xDA
+#define WIN_ACKMEDIACHANGE 0xDB /* ATA-1, ATA-2 vendor */
+#define WIN_POSTBOOT 0xDC
+#define WIN_PREBOOT 0xDD
+#define WIN_DOORLOCK 0xDE /* lock door on removable drives */
+#define WIN_DOORUNLOCK 0xDF /* unlock door on removable drives */
+#define WIN_STANDBYNOW1 0xE0
+#define WIN_IDLEIMMEDIATE 0xE1 /* force drive to become "ready" */
+#define WIN_STANDBY 0xE2 /* Set device in Standby Mode */
+#define WIN_SETIDLE1 0xE3
+#define WIN_READ_BUFFER 0xE4 /* force read only 1 sector */
+#define WIN_CHECKPOWERMODE1 0xE5
+#define WIN_SLEEPNOW1 0xE6
+#define WIN_FLUSH_CACHE 0xE7
+#define WIN_WRITE_BUFFER 0xE8 /* force write only 1 sector */
+#define WIN_WRITE_SAME 0xE9 /* read ata-2 to use */
+ /* SET_FEATURES 0x22 or 0xDD */
+#define WIN_FLUSH_CACHE_EXT 0xEA /* 48-Bit */
+#define WIN_IDENTIFY 0xEC /* ask drive to identify itself */
+#define WIN_MEDIAEJECT 0xED
+#define WIN_IDENTIFY_DMA 0xEE /* same as WIN_IDENTIFY, but DMA */
+#define WIN_SETFEATURES 0xEF /* set special drive features */
+#define EXABYTE_ENABLE_NEST 0xF0
+#define WIN_SECURITY_SET_PASS 0xF1
+#define WIN_SECURITY_UNLOCK 0xF2
+#define WIN_SECURITY_ERASE_PREPARE 0xF3
+#define WIN_SECURITY_ERASE_UNIT 0xF4
+#define WIN_SECURITY_FREEZE_LOCK 0xF5
+#define WIN_SECURITY_DISABLE 0xF6
+#define WIN_READ_NATIVE_MAX 0xF8 /* return the native maximum address */
+#define WIN_SET_MAX 0xF9
+#define DISABLE_SEAGATE 0xFB
+
+/* set to 1 set disable mult support */
+#define MAX_MULT_SECTORS 16
+
+/* ATAPI defines */
+
+#define ATAPI_PACKET_SIZE 12
+
+/* The generic packet command opcodes for CD/DVD Logical Units,
+ * From Table 57 of the SFF8090 Ver. 3 (Mt. Fuji) draft standard. */
+#define GPCMD_BLANK 0xa1
+#define GPCMD_CLOSE_TRACK 0x5b
+#define GPCMD_FLUSH_CACHE 0x35
+#define GPCMD_FORMAT_UNIT 0x04
+#define GPCMD_GET_CONFIGURATION 0x46
+#define GPCMD_GET_EVENT_STATUS_NOTIFICATION 0x4a
+#define GPCMD_GET_PERFORMANCE 0xac
+#define GPCMD_INQUIRY 0x12
+#define GPCMD_LOAD_UNLOAD 0xa6
+#define GPCMD_MECHANISM_STATUS 0xbd
+#define GPCMD_MODE_SELECT_10 0x55
+#define GPCMD_MODE_SENSE_10 0x5a
+#define GPCMD_PAUSE_RESUME 0x4b
+#define GPCMD_PLAY_AUDIO_10 0x45
+#define GPCMD_PLAY_AUDIO_MSF 0x47
+#define GPCMD_PLAY_AUDIO_TI 0x48
+#define GPCMD_PLAY_CD 0xbc
+#define GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e
+#define GPCMD_READ_10 0x28
+#define GPCMD_READ_12 0xa8
+#define GPCMD_READ_CDVD_CAPACITY 0x25
+#define GPCMD_READ_CD 0xbe
+#define GPCMD_READ_CD_MSF 0xb9
+#define GPCMD_READ_DISC_INFO 0x51
+#define GPCMD_READ_DVD_STRUCTURE 0xad
+#define GPCMD_READ_FORMAT_CAPACITIES 0x23
+#define GPCMD_READ_HEADER 0x44
+#define GPCMD_READ_TRACK_RZONE_INFO 0x52
+#define GPCMD_READ_SUBCHANNEL 0x42
+#define GPCMD_READ_TOC_PMA_ATIP 0x43
+#define GPCMD_REPAIR_RZONE_TRACK 0x58
+#define GPCMD_REPORT_KEY 0xa4
+#define GPCMD_REQUEST_SENSE 0x03
+#define GPCMD_RESERVE_RZONE_TRACK 0x53
+#define GPCMD_SCAN 0xba
+#define GPCMD_SEEK 0x2b
+#define GPCMD_SEND_DVD_STRUCTURE 0xad
+#define GPCMD_SEND_EVENT 0xa2
+#define GPCMD_SEND_KEY 0xa3
+#define GPCMD_SEND_OPC 0x54
+#define GPCMD_SET_READ_AHEAD 0xa7
+#define GPCMD_SET_STREAMING 0xb6
+#define GPCMD_START_STOP_UNIT 0x1b
+#define GPCMD_STOP_PLAY_SCAN 0x4e
+#define GPCMD_TEST_UNIT_READY 0x00
+#define GPCMD_VERIFY_10 0x2f
+#define GPCMD_WRITE_10 0x2a
+#define GPCMD_WRITE_AND_VERIFY_10 0x2e
+/* This is listed as optional in ATAPI 2.6, but is (curiously)
+ * missing from Mt. Fuji, Table 57. It _is_ mentioned in Mt. Fuji
+ * Table 377 as an MMC command for SCSi devices though... Most ATAPI
+ * drives support it. */
+#define GPCMD_SET_SPEED 0xbb
+/* This seems to be a SCSI specific CD-ROM opcode
+ * to play data at track/index */
+#define GPCMD_PLAYAUDIO_TI 0x48
+/*
+ * From MS Media Status Notification Support Specification. For
+ * older drives only.
+ */
+#define GPCMD_GET_MEDIA_STATUS 0xda
+
+/* Mode page codes for mode sense/set */
+#define GPMODE_R_W_ERROR_PAGE 0x01
+#define GPMODE_WRITE_PARMS_PAGE 0x05
+#define GPMODE_AUDIO_CTL_PAGE 0x0e
+#define GPMODE_POWER_PAGE 0x1a
+#define GPMODE_FAULT_FAIL_PAGE 0x1c
+#define GPMODE_TO_PROTECT_PAGE 0x1d
+#define GPMODE_CAPABILITIES_PAGE 0x2a
+#define GPMODE_ALL_PAGES 0x3f
+/* Not in Mt. Fuji, but in ATAPI 2.6 -- depricated now in favor
+ * of MODE_SENSE_POWER_PAGE */
+#define GPMODE_CDROM_PAGE 0x0d
+
+#define ATAPI_INT_REASON_CD 0x01 /* 0 = data transfer */
+#define ATAPI_INT_REASON_IO 0x02 /* 1 = transfer to the host */
+#define ATAPI_INT_REASON_REL 0x04
+#define ATAPI_INT_REASON_TAG 0xf8
+
+/* same constants as bochs */
+#define ASC_ILLEGAL_OPCODE 0x20
+#define ASC_LOGICAL_BLOCK_OOR 0x21
+#define ASC_INV_FIELD_IN_CMD_PACKET 0x24
+#define ASC_MEDIUM_NOT_PRESENT 0x3a
+#define ASC_SAVING_PARAMETERS_NOT_SUPPORTED 0x39
+
+#define SENSE_NONE 0
+#define SENSE_NOT_READY 2
+#define SENSE_ILLEGAL_REQUEST 5
+#define SENSE_UNIT_ATTENTION 6
+
+struct IDEState;
+
+typedef void EndTransferFunc(struct IDEState *);
+
+/* NOTE: IDEState represents in fact one drive */
+typedef struct IDEState {
+ /* ide config */
+ int is_cdrom;
+ int cylinders, heads, sectors;
+ int64_t nb_sectors;
+ int mult_sectors;
+ int irq;
+ openpic_t *openpic;
+ PCIDevice *pci_dev;
+ struct BMDMAState *bmdma;
+ int drive_serial;
+ /* ide regs */
+ uint8_t feature;
+ uint8_t error;
+ uint16_t nsector; /* 0 is 256 to ease computations */
+ uint8_t sector;
+ uint8_t lcyl;
+ uint8_t hcyl;
+ uint8_t select;
+ uint8_t status;
+ /* 0x3f6 command, only meaningful for drive 0 */
+ uint8_t cmd;
+ /* depends on bit 4 in select, only meaningful for drive 0 */
+ struct IDEState *cur_drive;
+ BlockDriverState *bs;
+ /* ATAPI specific */
+ uint8_t sense_key;
+ uint8_t asc;
+ int packet_transfer_size;
+ int elementary_transfer_size;
+ int io_buffer_index;
+ int lba;
+ int cd_sector_size;
+ int atapi_dma; /* true if dma is requested for the packet cmd */
+ /* ATA DMA state */
+ int io_buffer_size;
+ /* PIO transfer handling */
+ int req_nb_sectors; /* number of sectors per interrupt */
+ EndTransferFunc *end_transfer_func;
+ uint8_t *data_ptr;
+ uint8_t *data_end;
+ uint8_t io_buffer[MAX_MULT_SECTORS*512 + 4];
+} IDEState;
+
+#define BM_STATUS_DMAING 0x01
+#define BM_STATUS_ERROR 0x02
+#define BM_STATUS_INT 0x04
+
+#define BM_CMD_START 0x01
+#define BM_CMD_READ 0x08
+
+typedef int IDEDMAFunc(IDEState *s,
+ target_phys_addr_t phys_addr,
+ int transfer_size1);
+
+typedef struct BMDMAState {
+ uint8_t cmd;
+ uint8_t status;
+ uint32_t addr;
+ /* current transfer state */
+ IDEState *ide_if;
+ IDEDMAFunc *dma_cb;
+} BMDMAState;
+
+typedef struct PCIIDEState {
+ PCIDevice dev;
+ IDEState ide_if[4];
+ BMDMAState bmdma[2];
+} PCIIDEState;
+
+static void ide_dma_start(IDEState *s, IDEDMAFunc *dma_cb);
+
+static void padstr(char *str, const char *src, int len)
+{
+ int i, v;
+ for(i = 0; i < len; i++) {
+ if (*src)
+ v = *src++;
+ else
+ v = ' ';
+ *(char *)((long)str ^ 1) = v;
+ str++;
+ }
+}
+
+static void padstr8(uint8_t *buf, int buf_size, const char *src)
+{
+ int i;
+ for(i = 0; i < buf_size; i++) {
+ if (*src)
+ buf[i] = *src++;
+ else
+ buf[i] = ' ';
+ }
+}
+
+static void put_le16(uint16_t *p, unsigned int v)
+{
+ *p = cpu_to_le16(v);
+}
+
+static void ide_identify(IDEState *s)
+{
+ uint16_t *p;
+ unsigned int oldsize;
+ char buf[20];
+
+ memset(s->io_buffer, 0, 512);
+ p = (uint16_t *)s->io_buffer;
+ put_le16(p + 0, 0x0040);
+ put_le16(p + 1, s->cylinders);
+ put_le16(p + 3, s->heads);
+ put_le16(p + 4, 512 * s->sectors); /* XXX: retired, remove ? */
+ put_le16(p + 5, 512); /* XXX: retired, remove ? */
+ put_le16(p + 6, s->sectors);
+ snprintf(buf, sizeof(buf), "QM%05d", s->drive_serial);
+ padstr((uint8_t *)(p + 10), buf, 20); /* serial number */
+ put_le16(p + 20, 3); /* XXX: retired, remove ? */
+ put_le16(p + 21, 512); /* cache size in sectors */
+ put_le16(p + 22, 4); /* ecc bytes */
+ padstr((uint8_t *)(p + 23), QEMU_VERSION, 8); /* firmware version */
+ padstr((uint8_t *)(p + 27), "QEMU HARDDISK", 40); /* model */
+#if MAX_MULT_SECTORS > 1
+ put_le16(p + 47, 0x8000 | MAX_MULT_SECTORS);
+#endif
+ put_le16(p + 48, 1); /* dword I/O */
+ put_le16(p + 49, 1 << 9 | 1 << 8); /* DMA and LBA supported */
+ put_le16(p + 51, 0x200); /* PIO transfer cycle */
+ put_le16(p + 52, 0x200); /* DMA transfer cycle */
+ put_le16(p + 53, 1 | 1 << 2); /* words 54-58,88 are valid */
+ put_le16(p + 54, s->cylinders);
+ put_le16(p + 55, s->heads);
+ put_le16(p + 56, s->sectors);
+ oldsize = s->cylinders * s->heads * s->sectors;
+ put_le16(p + 57, oldsize);
+ put_le16(p + 58, oldsize >> 16);
+ if (s->mult_sectors)
+ put_le16(p + 59, 0x100 | s->mult_sectors);
+ put_le16(p + 60, s->nb_sectors);
+ put_le16(p + 61, s->nb_sectors >> 16);
+ put_le16(p + 80, (1 << 1) | (1 << 2));
+ put_le16(p + 82, (1 << 14));
+ put_le16(p + 83, (1 << 14));
+ put_le16(p + 84, (1 << 14));
+ put_le16(p + 85, (1 << 14));
+ put_le16(p + 86, 0);
+ put_le16(p + 87, (1 << 14));
+ put_le16(p + 88, 0x1f | (1 << 13));
+ put_le16(p + 93, 1 | (1 << 14) | 0x2000 | 0x4000);
+}
+
+static void ide_atapi_identify(IDEState *s)
+{
+ uint16_t *p;
+ char buf[20];
+
+ memset(s->io_buffer, 0, 512);
+ p = (uint16_t *)s->io_buffer;
+ /* Removable CDROM, 50us response, 12 byte packets */
+ put_le16(p + 0, (2 << 14) | (5 << 8) | (1 << 7) | (2 << 5) | (0 << 0));
+ snprintf(buf, sizeof(buf), "QM%05d", s->drive_serial);
+ padstr((uint8_t *)(p + 10), buf, 20); /* serial number */
+ put_le16(p + 20, 3); /* buffer type */
+ put_le16(p + 21, 512); /* cache size in sectors */
+ put_le16(p + 22, 4); /* ecc bytes */
+ padstr((uint8_t *)(p + 23), QEMU_VERSION, 8); /* firmware version */
+ padstr((uint8_t *)(p + 27), "QEMU CD-ROM", 40); /* model */
+ put_le16(p + 48, 1); /* dword I/O (XXX: should not be set on CDROM) */
+ put_le16(p + 49, 1 << 9); /* LBA supported, no DMA */
+ put_le16(p + 53, 3); /* words 64-70, 54-58 valid */
+ put_le16(p + 63, 0x103); /* DMA modes XXX: may be incorrect */
+ put_le16(p + 64, 1); /* PIO modes */
+ put_le16(p + 65, 0xb4); /* minimum DMA multiword tx cycle time */
+ put_le16(p + 66, 0xb4); /* recommended DMA multiword tx cycle time */
+ put_le16(p + 67, 0x12c); /* minimum PIO cycle time without flow control */
+ put_le16(p + 68, 0xb4); /* minimum PIO cycle time with IORDY flow control */
+
+ put_le16(p + 71, 30); /* in ns */
+ put_le16(p + 72, 30); /* in ns */
+
+ put_le16(p + 80, 0x1e); /* support up to ATA/ATAPI-4 */
+}
+
+static void ide_set_signature(IDEState *s)
+{
+ s->select &= 0xf0; /* clear head */
+ /* put signature */
+ s->nsector = 1;
+ s->sector = 1;
+ if (s->is_cdrom) {
+ s->lcyl = 0x14;
+ s->hcyl = 0xeb;
+ } else if (s->bs) {
+ s->lcyl = 0;
+ s->hcyl = 0;
+ } else {
+ s->lcyl = 0xff;
+ s->hcyl = 0xff;
+ }
+}
+
+static inline void ide_abort_command(IDEState *s)
+{
+ s->status = READY_STAT | ERR_STAT;
+ s->error = ABRT_ERR;
+}
+
+static inline void ide_set_irq(IDEState *s)
+{
+ if (!(s->cmd & IDE_CMD_DISABLE_IRQ)) {
+#ifdef TARGET_PPC
+ if (s->openpic)
+ openpic_set_irq(s->openpic, s->irq, 1);
+ else
+#endif
+ if (s->irq == 16)
+ pci_set_irq(s->pci_dev, 0, 1);
+ else
+ pic_set_irq(s->irq, 1);
+ }
+}
+
+/* prepare data transfer and tell what to do after */
+static void ide_transfer_start(IDEState *s, uint8_t *buf, int size,
+ EndTransferFunc *end_transfer_func)
+{
+ s->end_transfer_func = end_transfer_func;
+ s->data_ptr = buf;
+ s->data_end = buf + size;
+ s->status |= DRQ_STAT;
+}
+
+static void ide_transfer_stop(IDEState *s)
+{
+ s->end_transfer_func = ide_transfer_stop;
+ s->data_ptr = s->io_buffer;
+ s->data_end = s->io_buffer;
+ s->status &= ~DRQ_STAT;
+}
+
+static int64_t ide_get_sector(IDEState *s)
+{
+ int64_t sector_num;
+ if (s->select & 0x40) {
+ /* lba */
+ sector_num = ((s->select & 0x0f) << 24) | (s->hcyl << 16) |
+ (s->lcyl << 8) | s->sector;
+ } else {
+ sector_num = ((s->hcyl << 8) | s->lcyl) * s->heads * s->sectors +
+ (s->select & 0x0f) * s->sectors +
+ (s->sector - 1);
+ }
+ return sector_num;
+}
+
+static void ide_set_sector(IDEState *s, int64_t sector_num)
+{
+ unsigned int cyl, r;
+ if (s->select & 0x40) {
+ s->select = (s->select & 0xf0) | (sector_num >> 24);
+ s->hcyl = (sector_num >> 16);
+ s->lcyl = (sector_num >> 8);
+ s->sector = (sector_num);
+ } else {
+ cyl = sector_num / (s->heads * s->sectors);
+ r = sector_num % (s->heads * s->sectors);
+ s->hcyl = cyl >> 8;
+ s->lcyl = cyl;
+ s->select = (s->select & 0xf0) | ((r / s->sectors) & 0x0f);
+ s->sector = (r % s->sectors) + 1;
+ }
+}
+
+static void ide_sector_read(IDEState *s)
+{
+ int64_t sector_num;
+ int ret, n;
+
+ s->status = READY_STAT | SEEK_STAT;
+ s->error = 0; /* not needed by IDE spec, but needed by Windows */
+ sector_num = ide_get_sector(s);
+ n = s->nsector;
+ if (n == 0) {
+ /* no more sector to read from disk */
+ ide_transfer_stop(s);
+ } else {
+#if defined(DEBUG_IDE)
+ printf("read sector=%Ld\n", sector_num);
+#endif
+ if (n > s->req_nb_sectors)
+ n = s->req_nb_sectors;
+ ret = bdrv_read(s->bs, sector_num, s->io_buffer, n);
+ ide_transfer_start(s, s->io_buffer, 512 * n, ide_sector_read);
+ ide_set_irq(s);
+ ide_set_sector(s, sector_num + n);
+ s->nsector -= n;
+ }
+}
+
+static int ide_read_dma_cb(IDEState *s,
+ target_phys_addr_t phys_addr,
+ int transfer_size1)
+{
+ int len, transfer_size, n;
+ int64_t sector_num;
+
+ transfer_size = transfer_size1;
+ while (transfer_size > 0) {
+ len = s->io_buffer_size - s->io_buffer_index;
+ if (len <= 0) {
+ /* transfert next data */
+ n = s->nsector;
+ if (n == 0)
+ break;
+ if (n > MAX_MULT_SECTORS)
+ n = MAX_MULT_SECTORS;
+ sector_num = ide_get_sector(s);
+ bdrv_read(s->bs, sector_num, s->io_buffer, n);
+ s->io_buffer_index = 0;
+ s->io_buffer_size = n * 512;
+ len = s->io_buffer_size;
+ sector_num += n;
+ ide_set_sector(s, sector_num);
+ s->nsector -= n;
+ }
+ if (len > transfer_size)
+ len = transfer_size;
+ cpu_physical_memory_write(phys_addr,
+ s->io_buffer + s->io_buffer_index, len);
+ s->io_buffer_index += len;
+ transfer_size -= len;
+ phys_addr += len;
+ }
+ if (s->io_buffer_index >= s->io_buffer_size && s->nsector == 0) {
+ s->status = READY_STAT | SEEK_STAT;
+ ide_set_irq(s);
+#ifdef DEBUG_IDE_ATAPI
+ printf("dma status=0x%x\n", s->status);
+#endif
+ return 0;
+ }
+ return transfer_size1 - transfer_size;
+}
+
+static void ide_sector_read_dma(IDEState *s)
+{
+ s->status = READY_STAT | SEEK_STAT | DRQ_STAT;
+ s->io_buffer_index = 0;
+ s->io_buffer_size = 0;
+ ide_dma_start(s, ide_read_dma_cb);
+}
+
+static void ide_sector_write(IDEState *s)
+{
+ int64_t sector_num;
+ int ret, n, n1;
+
+ s->status = READY_STAT | SEEK_STAT;
+ sector_num = ide_get_sector(s);
+#if defined(DEBUG_IDE)
+ printf("write sector=%Ld\n", sector_num);
+#endif
+ n = s->nsector;
+ if (n > s->req_nb_sectors)
+ n = s->req_nb_sectors;
+ ret = bdrv_write(s->bs, sector_num, s->io_buffer, n);
+ s->nsector -= n;
+ if (s->nsector == 0) {
+ /* no more sector to write */
+ ide_transfer_stop(s);
+ } else {
+ n1 = s->nsector;
+ if (n1 > s->req_nb_sectors)
+ n1 = s->req_nb_sectors;
+ ide_transfer_start(s, s->io_buffer, 512 * n1, ide_sector_write);
+ }
+ ide_set_sector(s, sector_num + n);
+ ide_set_irq(s);
+}
+
+static int ide_write_dma_cb(IDEState *s,
+ target_phys_addr_t phys_addr,
+ int transfer_size1)
+{
+ int len, transfer_size, n;
+ int64_t sector_num;
+
+ transfer_size = transfer_size1;
+ for(;;) {
+ len = s->io_buffer_size - s->io_buffer_index;
+ if (len == 0) {
+ n = s->io_buffer_size >> 9;
+ sector_num = ide_get_sector(s);
+ bdrv_write(s->bs, sector_num, s->io_buffer,
+ s->io_buffer_size >> 9);
+ sector_num += n;
+ ide_set_sector(s, sector_num);
+ s->nsector -= n;
+ n = s->nsector;
+ if (n == 0) {
+ /* end of transfer */
+ s->status = READY_STAT | SEEK_STAT;
+ ide_set_irq(s);
+ return 0;
+ }
+ if (n > MAX_MULT_SECTORS)
+ n = MAX_MULT_SECTORS;
+ s->io_buffer_index = 0;
+ s->io_buffer_size = n * 512;
+ len = s->io_buffer_size;
+ }
+ if (transfer_size <= 0)
+ break;
+ if (len > transfer_size)
+ len = transfer_size;
+ cpu_physical_memory_read(phys_addr,
+ s->io_buffer + s->io_buffer_index, len);
+ s->io_buffer_index += len;
+ transfer_size -= len;
+ phys_addr += len;
+ }
+ return transfer_size1 - transfer_size;
+}
+
+static void ide_sector_write_dma(IDEState *s)
+{
+ int n;
+ s->status = READY_STAT | SEEK_STAT | DRQ_STAT;
+ n = s->nsector;
+ if (n > MAX_MULT_SECTORS)
+ n = MAX_MULT_SECTORS;
+ s->io_buffer_index = 0;
+ s->io_buffer_size = n * 512;
+ ide_dma_start(s, ide_write_dma_cb);
+}
+
+static void ide_atapi_cmd_ok(IDEState *s)
+{
+ s->error = 0;
+ s->status = READY_STAT;
+ s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
+ ide_set_irq(s);
+}
+
+static void ide_atapi_cmd_error(IDEState *s, int sense_key, int asc)
+{
+#ifdef DEBUG_IDE_ATAPI
+ printf("atapi_cmd_error: sense=0x%x asc=0x%x\n", sense_key, asc);
+#endif
+ s->error = sense_key << 4;
+ s->status = READY_STAT | ERR_STAT;
+ s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
+ s->sense_key = sense_key;
+ s->asc = asc;
+ ide_set_irq(s);
+}
+
+static inline void cpu_to_ube16(uint8_t *buf, int val)
+{
+ buf[0] = val >> 8;
+ buf[1] = val;
+}
+
+static inline void cpu_to_ube32(uint8_t *buf, unsigned int val)
+{
+ buf[0] = val >> 24;
+ buf[1] = val >> 16;
+ buf[2] = val >> 8;
+ buf[3] = val;
+}
+
+static inline int ube16_to_cpu(const uint8_t *buf)
+{
+ return (buf[0] << 8) | buf[1];
+}
+
+static inline int ube32_to_cpu(const uint8_t *buf)
+{
+ return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
+}
+
+static void lba_to_msf(uint8_t *buf, int lba)
+{
+ lba += 150;
+ buf[0] = (lba / 75) / 60;
+ buf[1] = (lba / 75) % 60;
+ buf[2] = lba % 75;
+}
+
+static void cd_read_sector(BlockDriverState *bs, int lba, uint8_t *buf,
+ int sector_size)
+{
+ switch(sector_size) {
+ case 2048:
+ bdrv_read(bs, (int64_t)lba << 2, buf, 4);
+ break;
+ case 2352:
+ /* sync bytes */
+ buf[0] = 0x00;
+ memset(buf + 1, 0xff, 11);
+ buf += 12;
+ /* MSF */
+ lba_to_msf(buf, lba);
+ buf[3] = 0x01; /* mode 1 data */
+ buf += 4;
+ /* data */
+ bdrv_read(bs, (int64_t)lba << 2, buf, 4);
+ buf += 2048;
+ /* ECC */
+ memset(buf, 0, 288);
+ break;
+ default:
+ break;
+ }
+}
+
+/* The whole ATAPI transfer logic is handled in this function */
+static void ide_atapi_cmd_reply_end(IDEState *s)
+{
+ int byte_count_limit, size;
+#ifdef DEBUG_IDE_ATAPI
+ printf("reply: tx_size=%d elem_tx_size=%d index=%d\n",
+ s->packet_transfer_size,
+ s->elementary_transfer_size,
+ s->io_buffer_index);
+#endif
+ if (s->packet_transfer_size <= 0) {
+ /* end of transfer */
+ ide_transfer_stop(s);
+ s->status = READY_STAT;
+ s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
+ ide_set_irq(s);
+#ifdef DEBUG_IDE_ATAPI
+ printf("status=0x%x\n", s->status);
+#endif
+ } else {
+ /* see if a new sector must be read */
+ if (s->lba != -1 && s->io_buffer_index >= s->cd_sector_size) {
+ cd_read_sector(s->bs, s->lba, s->io_buffer, s->cd_sector_size);
+ s->lba++;
+ s->io_buffer_index = 0;
+ }
+ if (s->elementary_transfer_size > 0) {
+ /* there are some data left to transmit in this elementary
+ transfer */
+ size = s->cd_sector_size - s->io_buffer_index;
+ if (size > s->elementary_transfer_size)
+ size = s->elementary_transfer_size;
+ ide_transfer_start(s, s->io_buffer + s->io_buffer_index,
+ size, ide_atapi_cmd_reply_end);
+ s->packet_transfer_size -= size;
+ s->elementary_transfer_size -= size;
+ s->io_buffer_index += size;
+ } else {
+ /* a new transfer is needed */
+ s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO;
+ byte_count_limit = s->lcyl | (s->hcyl << 8);
+#ifdef DEBUG_IDE_ATAPI
+ printf("byte_count_limit=%d\n", byte_count_limit);
+#endif
+ if (byte_count_limit == 0xffff)
+ byte_count_limit--;
+ size = s->packet_transfer_size;
+ if (size > byte_count_limit) {
+ /* byte count limit must be even if this case */
+ if (byte_count_limit & 1)
+ byte_count_limit--;
+ size = byte_count_limit;
+ }
+ s->lcyl = size;
+ s->hcyl = size >> 8;
+ s->elementary_transfer_size = size;
+ /* we cannot transmit more than one sector at a time */
+ if (s->lba != -1) {
+ if (size > (s->cd_sector_size - s->io_buffer_index))
+ size = (s->cd_sector_size - s->io_buffer_index);
+ }
+ ide_transfer_start(s, s->io_buffer + s->io_buffer_index,
+ size, ide_atapi_cmd_reply_end);
+ s->packet_transfer_size -= size;
+ s->elementary_transfer_size -= size;
+ s->io_buffer_index += size;
+ ide_set_irq(s);
+#ifdef DEBUG_IDE_ATAPI
+ printf("status=0x%x\n", s->status);
+#endif
+ }
+ }
+}
+
+/* send a reply of 'size' bytes in s->io_buffer to an ATAPI command */
+static void ide_atapi_cmd_reply(IDEState *s, int size, int max_size)
+{
+ if (size > max_size)
+ size = max_size;
+ s->lba = -1; /* no sector read */
+ s->packet_transfer_size = size;
+ s->elementary_transfer_size = 0;
+ s->io_buffer_index = 0;
+
+ s->status = READY_STAT;
+ ide_atapi_cmd_reply_end(s);
+}
+
+/* start a CD-CDROM read command */
+static void ide_atapi_cmd_read_pio(IDEState *s, int lba, int nb_sectors,
+ int sector_size)
+{
+ s->lba = lba;
+ s->packet_transfer_size = nb_sectors * sector_size;
+ s->elementary_transfer_size = 0;
+ s->io_buffer_index = sector_size;
+ s->cd_sector_size = sector_size;
+
+ s->status = READY_STAT;
+ ide_atapi_cmd_reply_end(s);
+}
+
+/* ATAPI DMA support */
+static int ide_atapi_cmd_read_dma_cb(IDEState *s,
+ target_phys_addr_t phys_addr,
+ int transfer_size1)
+{
+ int len, transfer_size;
+
+ transfer_size = transfer_size1;
+ while (transfer_size > 0) {
+ if (s->packet_transfer_size <= 0)
+ break;
+ len = s->cd_sector_size - s->io_buffer_index;
+ if (len <= 0) {
+ /* transfert next data */
+ cd_read_sector(s->bs, s->lba, s->io_buffer, s->cd_sector_size);
+ s->lba++;
+ s->io_buffer_index = 0;
+ len = s->cd_sector_size;
+ }
+ if (len > transfer_size)
+ len = transfer_size;
+ cpu_physical_memory_write(phys_addr,
+ s->io_buffer + s->io_buffer_index, len);
+ s->packet_transfer_size -= len;
+ s->io_buffer_index += len;
+ transfer_size -= len;
+ phys_addr += len;
+ }
+ if (s->packet_transfer_size <= 0) {
+ s->status = READY_STAT;
+ s->nsector = (s->nsector & ~7) | ATAPI_INT_REASON_IO | ATAPI_INT_REASON_CD;
+ ide_set_irq(s);
+#ifdef DEBUG_IDE_ATAPI
+ printf("dma status=0x%x\n", s->status);
+#endif
+ return 0;
+ }
+ return transfer_size1 - transfer_size;
+}
+
+/* start a CD-CDROM read command with DMA */
+/* XXX: test if DMA is available */
+static void ide_atapi_cmd_read_dma(IDEState *s, int lba, int nb_sectors,
+ int sector_size)
+{
+ s->lba = lba;
+ s->packet_transfer_size = nb_sectors * sector_size;
+ s->io_buffer_index = sector_size;
+ s->cd_sector_size = sector_size;
+
+ s->status = READY_STAT | DRQ_STAT;
+ ide_dma_start(s, ide_atapi_cmd_read_dma_cb);
+}
+
+static void ide_atapi_cmd_read(IDEState *s, int lba, int nb_sectors,
+ int sector_size)
+{
+#ifdef DEBUG_IDE_ATAPI
+ printf("read: LBA=%d nb_sectors=%d\n", lba, nb_sectors);
+#endif
+ if (s->atapi_dma) {
+ ide_atapi_cmd_read_dma(s, lba, nb_sectors, sector_size);
+ } else {
+ ide_atapi_cmd_read_pio(s, lba, nb_sectors, sector_size);
+ }
+}
+
+/* same toc as bochs. Return -1 if error or the toc length */
+/* XXX: check this */
+static int cdrom_read_toc(IDEState *s, uint8_t *buf, int msf, int start_track)
+{
+ uint8_t *q;
+ int nb_sectors, len;
+
+ if (start_track > 1 && start_track != 0xaa)
+ return -1;
+ q = buf + 2;
+ *q++ = 1; /* first session */
+ *q++ = 1; /* last session */
+ if (start_track <= 1) {
+ *q++ = 0; /* reserved */
+ *q++ = 0x14; /* ADR, control */
+ *q++ = 1; /* track number */
+ *q++ = 0; /* reserved */
+ if (msf) {
+ *q++ = 0; /* reserved */
+ *q++ = 0; /* minute */
+ *q++ = 2; /* second */
+ *q++ = 0; /* frame */
+ } else {
+ /* sector 0 */
+ cpu_to_ube32(q, 0);
+ q += 4;
+ }
+ }
+ /* lead out track */
+ *q++ = 0; /* reserved */
+ *q++ = 0x16; /* ADR, control */
+ *q++ = 0xaa; /* track number */
+ *q++ = 0; /* reserved */
+ nb_sectors = s->nb_sectors >> 2;
+ if (msf) {
+ *q++ = 0; /* reserved */
+ lba_to_msf(q, nb_sectors);
+ q += 3;
+ } else {
+ cpu_to_ube32(q, nb_sectors);
+ q += 4;
+ }
+ len = q - buf;
+ cpu_to_ube16(buf, len - 2);
+ return len;
+}
+
+/* mostly same info as PearPc */
+static int cdrom_read_toc_raw(IDEState *s, uint8_t *buf, int msf,
+ int session_num)
+{
+ uint8_t *q;
+ int nb_sectors, len;
+
+ q = buf + 2;
+ *q++ = 1; /* first session */
+ *q++ = 1; /* last session */
+
+ *q++ = 1; /* session number */
+ *q++ = 0x14; /* data track */
+ *q++ = 0; /* track number */
+ *q++ = 0xa0; /* lead-in */
+ *q++ = 0; /* min */
+ *q++ = 0; /* sec */
+ *q++ = 0; /* frame */
+ *q++ = 0;
+ *q++ = 1; /* first track */
+ *q++ = 0x00; /* disk type */
+ *q++ = 0x00;
+
+ *q++ = 1; /* session number */
+ *q++ = 0x14; /* data track */
+ *q++ = 0; /* track number */
+ *q++ = 0xa1;
+ *q++ = 0; /* min */
+ *q++ = 0; /* sec */
+ *q++ = 0; /* frame */
+ *q++ = 0;
+ *q++ = 1; /* last track */
+ *q++ = 0x00;
+ *q++ = 0x00;
+
+ *q++ = 1; /* session number */
+ *q++ = 0x14; /* data track */
+ *q++ = 0; /* track number */
+ *q++ = 0xa2; /* lead-out */
+ *q++ = 0; /* min */
+ *q++ = 0; /* sec */
+ *q++ = 0; /* frame */
+ nb_sectors = s->nb_sectors >> 2;
+ if (msf) {
+ *q++ = 0; /* reserved */
+ lba_to_msf(q, nb_sectors);
+ q += 3;
+ } else {
+ cpu_to_ube32(q, nb_sectors);
+ q += 4;
+ }
+
+ *q++ = 1; /* session number */
+ *q++ = 0x14; /* ADR, control */
+ *q++ = 0; /* track number */
+ *q++ = 1; /* point */
+ *q++ = 0; /* min */
+ *q++ = 0; /* sec */
+ *q++ = 0; /* frame */
+ *q++ = 0;
+ *q++ = 0;
+ *q++ = 0;
+ *q++ = 0;
+
+ len = q - buf;
+ cpu_to_ube16(buf, len - 2);
+ return len;
+}
+
+static void ide_atapi_cmd(IDEState *s)
+{
+ const uint8_t *packet;
+ uint8_t *buf;
+ int max_len;
+
+ packet = s->io_buffer;
+ buf = s->io_buffer;
+#ifdef DEBUG_IDE_ATAPI
+ {
+ int i;
+ printf("ATAPI limit=0x%x packet:", s->lcyl | (s->hcyl << 8));
+ for(i = 0; i < ATAPI_PACKET_SIZE; i++) {
+ printf(" %02x", packet[i]);
+ }
+ printf("\n");
+ }
+#endif
+ switch(s->io_buffer[0]) {
+ case GPCMD_TEST_UNIT_READY:
+ if (bdrv_is_inserted(s->bs)) {
+ ide_atapi_cmd_ok(s);
+ } else {
+ ide_atapi_cmd_error(s, SENSE_NOT_READY,
+ ASC_MEDIUM_NOT_PRESENT);
+ }
+ break;
+ case GPCMD_MODE_SENSE_10:
+ {
+ int action, code;
+ max_len = ube16_to_cpu(packet + 7);
+ action = packet[2] >> 6;
+ code = packet[2] & 0x3f;
+ switch(action) {
+ case 0: /* current values */
+ switch(code) {
+ case 0x01: /* error recovery */
+ cpu_to_ube16(&buf[0], 16 + 6);
+ buf[2] = 0x70;
+ buf[3] = 0;
+ buf[4] = 0;
+ buf[5] = 0;
+ buf[6] = 0;
+ buf[7] = 0;
+
+ buf[8] = 0x01;
+ buf[9] = 0x06;
+ buf[10] = 0x00;
+ buf[11] = 0x05;
+ buf[12] = 0x00;
+ buf[13] = 0x00;
+ buf[14] = 0x00;
+ buf[15] = 0x00;
+ ide_atapi_cmd_reply(s, 16, max_len);
+ break;
+ case 0x2a:
+ cpu_to_ube16(&buf[0], 28 + 6);
+ buf[2] = 0x70;
+ buf[3] = 0;
+ buf[4] = 0;
+ buf[5] = 0;
+ buf[6] = 0;
+ buf[7] = 0;
+
+ buf[8] = 0x2a;
+ buf[9] = 0x12;
+ buf[10] = 0x00;
+ buf[11] = 0x00;
+
+ buf[12] = 0x70;
+ buf[13] = 3 << 5;
+ buf[14] = (1 << 0) | (1 << 3) | (1 << 5);
+ if (bdrv_is_locked(s->bs))
+ buf[6] |= 1 << 1;
+ buf[15] = 0x00;
+ cpu_to_ube16(&buf[16], 706);
+ buf[18] = 0;
+ buf[19] = 2;
+ cpu_to_ube16(&buf[20], 512);
+ cpu_to_ube16(&buf[22], 706);
+ buf[24] = 0;
+ buf[25] = 0;
+ buf[26] = 0;
+ buf[27] = 0;
+ ide_atapi_cmd_reply(s, 28, max_len);
+ break;
+ default:
+ goto error_cmd;
+ }
+ break;
+ case 1: /* changeable values */
+ goto error_cmd;
+ case 2: /* default values */
+ goto error_cmd;
+ default:
+ case 3: /* saved values */
+ ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+ ASC_SAVING_PARAMETERS_NOT_SUPPORTED);
+ break;
+ }
+ }
+ break;
+ case GPCMD_REQUEST_SENSE:
+ max_len = packet[4];
+ memset(buf, 0, 18);
+ buf[0] = 0x70 | (1 << 7);
+ buf[2] = s->sense_key;
+ buf[7] = 10;
+ buf[12] = s->asc;
+ ide_atapi_cmd_reply(s, 18, max_len);
+ break;
+ case GPCMD_PREVENT_ALLOW_MEDIUM_REMOVAL:
+ if (bdrv_is_inserted(s->bs)) {
+ bdrv_set_locked(s->bs, packet[4] & 1);
+ ide_atapi_cmd_ok(s);
+ } else {
+ ide_atapi_cmd_error(s, SENSE_NOT_READY,
+ ASC_MEDIUM_NOT_PRESENT);
+ }
+ break;
+ case GPCMD_READ_10:
+ case GPCMD_READ_12:
+ {
+ int nb_sectors, lba;
+
+ if (!bdrv_is_inserted(s->bs)) {
+ ide_atapi_cmd_error(s, SENSE_NOT_READY,
+ ASC_MEDIUM_NOT_PRESENT);
+ break;
+ }
+ if (packet[0] == GPCMD_READ_10)
+ nb_sectors = ube16_to_cpu(packet + 7);
+ else
+ nb_sectors = ube32_to_cpu(packet + 6);
+ lba = ube32_to_cpu(packet + 2);
+ if (nb_sectors == 0) {
+ ide_atapi_cmd_ok(s);
+ break;
+ }
+ if (((int64_t)(lba + nb_sectors) << 2) > s->nb_sectors) {
+ ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+ ASC_LOGICAL_BLOCK_OOR);
+ break;
+ }
+ ide_atapi_cmd_read(s, lba, nb_sectors, 2048);
+ }
+ break;
+ case GPCMD_READ_CD:
+ {
+ int nb_sectors, lba, transfer_request;
+
+ if (!bdrv_is_inserted(s->bs)) {
+ ide_atapi_cmd_error(s, SENSE_NOT_READY,
+ ASC_MEDIUM_NOT_PRESENT);
+ break;
+ }
+ nb_sectors = (packet[6] << 16) | (packet[7] << 8) | packet[8];
+ lba = ube32_to_cpu(packet + 2);
+ if (nb_sectors == 0) {
+ ide_atapi_cmd_ok(s);
+ break;
+ }
+ if (((int64_t)(lba + nb_sectors) << 2) > s->nb_sectors) {
+ ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+ ASC_LOGICAL_BLOCK_OOR);
+ break;
+ }
+ transfer_request = packet[9];
+ switch(transfer_request & 0xf8) {
+ case 0x00:
+ /* nothing */
+ ide_atapi_cmd_ok(s);
+ break;
+ case 0x10:
+ /* normal read */
+ ide_atapi_cmd_read(s, lba, nb_sectors, 2048);
+ break;
+ case 0xf8:
+ /* read all data */
+ ide_atapi_cmd_read(s, lba, nb_sectors, 2352);
+ break;
+ default:
+ ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+ ASC_INV_FIELD_IN_CMD_PACKET);
+ break;
+ }
+ }
+ break;
+ case GPCMD_SEEK:
+ {
+ int lba;
+ if (!bdrv_is_inserted(s->bs)) {
+ ide_atapi_cmd_error(s, SENSE_NOT_READY,
+ ASC_MEDIUM_NOT_PRESENT);
+ break;
+ }
+ lba = ube32_to_cpu(packet + 2);
+ if (((int64_t)lba << 2) > s->nb_sectors) {
+ ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+ ASC_LOGICAL_BLOCK_OOR);
+ break;
+ }
+ ide_atapi_cmd_ok(s);
+ }
+ break;
+ case GPCMD_START_STOP_UNIT:
+ {
+ int start, eject;
+ start = packet[4] & 1;
+ eject = (packet[4] >> 1) & 1;
+
+ if (eject && !start) {
+ /* eject the disk */
+ bdrv_close(s->bs);
+ }
+ ide_atapi_cmd_ok(s);
+ }
+ break;
+ case GPCMD_MECHANISM_STATUS:
+ {
+ max_len = ube16_to_cpu(packet + 8);
+ cpu_to_ube16(buf, 0);
+ /* no current LBA */
+ buf[2] = 0;
+ buf[3] = 0;
+ buf[4] = 0;
+ buf[5] = 1;
+ cpu_to_ube16(buf + 6, 0);
+ ide_atapi_cmd_reply(s, 8, max_len);
+ }
+ break;
+ case GPCMD_READ_TOC_PMA_ATIP:
+ {
+ int format, msf, start_track, len;
+
+ if (!bdrv_is_inserted(s->bs)) {
+ ide_atapi_cmd_error(s, SENSE_NOT_READY,
+ ASC_MEDIUM_NOT_PRESENT);
+ break;
+ }
+ max_len = ube16_to_cpu(packet + 7);
+ format = packet[9] >> 6;
+ msf = (packet[1] >> 1) & 1;
+ start_track = packet[6];
+ switch(format) {
+ case 0:
+ len = cdrom_read_toc(s, buf, msf, start_track);
+ if (len < 0)
+ goto error_cmd;
+ ide_atapi_cmd_reply(s, len, max_len);
+ break;
+ case 1:
+ /* multi session : only a single session defined */
+ memset(buf, 0, 12);
+ buf[1] = 0x0a;
+ buf[2] = 0x01;
+ buf[3] = 0x01;
+ ide_atapi_cmd_reply(s, 12, max_len);
+ break;
+ case 2:
+ len = cdrom_read_toc_raw(s, buf, msf, start_track);
+ if (len < 0)
+ goto error_cmd;
+ ide_atapi_cmd_reply(s, len, max_len);
+ break;
+ default:
+ error_cmd:
+ ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+ ASC_INV_FIELD_IN_CMD_PACKET);
+ break;
+ }
+ }
+ break;
+ case GPCMD_READ_CDVD_CAPACITY:
+ if (!bdrv_is_inserted(s->bs)) {
+ ide_atapi_cmd_error(s, SENSE_NOT_READY,
+ ASC_MEDIUM_NOT_PRESENT);
+ break;
+ }
+ /* NOTE: it is really the number of sectors minus 1 */
+ cpu_to_ube32(buf, (s->nb_sectors >> 2) - 1);
+ cpu_to_ube32(buf + 4, 2048);
+ ide_atapi_cmd_reply(s, 8, 8);
+ break;
+ case GPCMD_INQUIRY:
+ max_len = packet[4];
+ buf[0] = 0x05; /* CD-ROM */
+ buf[1] = 0x80; /* removable */
+ buf[2] = 0x00; /* ISO */
+ buf[3] = 0x21; /* ATAPI-2 (XXX: put ATAPI-4 ?) */
+ buf[4] = 31; /* additionnal length */
+ buf[5] = 0; /* reserved */
+ buf[6] = 0; /* reserved */
+ buf[7] = 0; /* reserved */
+ padstr8(buf + 8, 8, "QEMU");
+ padstr8(buf + 16, 16, "QEMU CD-ROM");
+ padstr8(buf + 32, 4, QEMU_VERSION);
+ ide_atapi_cmd_reply(s, 36, max_len);
+ break;
+ default:
+ ide_atapi_cmd_error(s, SENSE_ILLEGAL_REQUEST,
+ ASC_ILLEGAL_OPCODE);
+ break;
+ }
+}
+
+/* called when the inserted state of the media has changed */
+static void cdrom_change_cb(void *opaque)
+{
+ IDEState *s = opaque;
+ int64_t nb_sectors;
+
+ /* XXX: send interrupt too */
+ bdrv_get_geometry(s->bs, &nb_sectors);
+ s->nb_sectors = nb_sectors;
+}
+
+static void ide_ioport_write(void *opaque, uint32_t addr, uint32_t val)
+{
+ IDEState *ide_if = opaque;
+ IDEState *s;
+ int unit, n;
+
+#ifdef DEBUG_IDE
+ printf("IDE: write addr=0x%x val=0x%02x\n", addr, val);
+#endif
+ addr &= 7;
+ switch(addr) {
+ case 0:
+ break;
+ case 1:
+ /* NOTE: data is written to the two drives */
+ ide_if[0].feature = val;
+ ide_if[1].feature = val;
+ break;
+ case 2:
+ if (val == 0)
+ val = 256;
+ ide_if[0].nsector = val;
+ ide_if[1].nsector = val;
+ break;
+ case 3:
+ ide_if[0].sector = val;
+ ide_if[1].sector = val;
+ break;
+ case 4:
+ ide_if[0].lcyl = val;
+ ide_if[1].lcyl = val;
+ break;
+ case 5:
+ ide_if[0].hcyl = val;
+ ide_if[1].hcyl = val;
+ break;
+ case 6:
+ ide_if[0].select = (val & ~0x10) | 0xa0;
+ ide_if[1].select = (val | 0x10) | 0xa0;
+ /* select drive */
+ unit = (val >> 4) & 1;
+ s = ide_if + unit;
+ ide_if->cur_drive = s;
+ break;
+ default:
+ case 7:
+ /* command */
+#if defined(DEBUG_IDE)
+ printf("ide: CMD=%02x\n", val);
+#endif
+ s = ide_if->cur_drive;
+ /* ignore commands to non existant slave */
+ if (s != ide_if && !s->bs)
+ break;
+ switch(val) {
+ case WIN_IDENTIFY:
+ if (s->bs && !s->is_cdrom) {
+ ide_identify(s);
+ s->status = READY_STAT | SEEK_STAT;
+ ide_transfer_start(s, s->io_buffer, 512, ide_transfer_stop);
+ } else {
+ if (s->is_cdrom) {
+ ide_set_signature(s);
+ }
+ ide_abort_command(s);
+ }
+ ide_set_irq(s);
+ break;
+ case WIN_SPECIFY:
+ case WIN_RECAL:
+ s->error = 0;
+ s->status = READY_STAT | SEEK_STAT;
+ ide_set_irq(s);
+ break;
+ case WIN_SETMULT:
+ if (s->nsector > MAX_MULT_SECTORS ||
+ s->nsector == 0 ||
+ (s->nsector & (s->nsector - 1)) != 0) {
+ ide_abort_command(s);
+ } else {
+ s->mult_sectors = s->nsector;
+ s->status = READY_STAT;
+ }
+ ide_set_irq(s);
+ break;
+ case WIN_VERIFY:
+ case WIN_VERIFY_ONCE:
+ /* do sector number check ? */
+ s->status = READY_STAT;
+ ide_set_irq(s);
+ break;
+ case WIN_READ:
+ case WIN_READ_ONCE:
+ if (!s->bs)
+ goto abort_cmd;
+ s->req_nb_sectors = 1;
+ ide_sector_read(s);
+ break;
+ case WIN_WRITE:
+ case WIN_WRITE_ONCE:
+ s->error = 0;
+ s->status = SEEK_STAT | READY_STAT;
+ s->req_nb_sectors = 1;
+ ide_transfer_start(s, s->io_buffer, 512, ide_sector_write);
+ break;
+ case WIN_MULTREAD:
+ if (!s->mult_sectors)
+ goto abort_cmd;
+ s->req_nb_sectors = s->mult_sectors;
+ ide_sector_read(s);
+ break;
+ case WIN_MULTWRITE:
+ if (!s->mult_sectors)
+ goto abort_cmd;
+ s->error = 0;
+ s->status = SEEK_STAT | READY_STAT;
+ s->req_nb_sectors = s->mult_sectors;
+ n = s->nsector;
+ if (n > s->req_nb_sectors)
+ n = s->req_nb_sectors;
+ ide_transfer_start(s, s->io_buffer, 512 * n, ide_sector_write);
+ break;
+ case WIN_READDMA:
+ case WIN_READDMA_ONCE:
+ if (!s->bs)
+ goto abort_cmd;
+ ide_sector_read_dma(s);
+ break;
+ case WIN_WRITEDMA:
+ case WIN_WRITEDMA_ONCE:
+ if (!s->bs)
+ goto abort_cmd;
+ ide_sector_write_dma(s);
+ break;
+ case WIN_READ_NATIVE_MAX:
+ ide_set_sector(s, s->nb_sectors - 1);
+ s->status = READY_STAT;
+ ide_set_irq(s);
+ break;
+ case WIN_CHECKPOWERMODE1:
+ s->nsector = 0xff; /* device active or idle */
+ s->status = READY_STAT;
+ ide_set_irq(s);
+ break;
+ case WIN_SETFEATURES:
+ if (!s->bs)
+ goto abort_cmd;
+ /* XXX: valid for CDROM ? */
+ switch(s->feature) {
+ case 0x02: /* write cache enable */
+ case 0x03: /* set transfer mode */
+ case 0x82: /* write cache disable */
+ case 0xaa: /* read look-ahead enable */
+ case 0x55: /* read look-ahead disable */
+ s->status = READY_STAT | SEEK_STAT;
+ ide_set_irq(s);
+ break;
+ default:
+ goto abort_cmd;
+ }
+ break;
+ case WIN_STANDBYNOW1:
+ s->status = READY_STAT;
+ ide_set_irq(s);
+ break;
+ /* ATAPI commands */
+ case WIN_PIDENTIFY:
+ if (s->is_cdrom) {
+ ide_atapi_identify(s);
+ s->status = READY_STAT;
+ ide_transfer_start(s, s->io_buffer, 512, ide_transfer_stop);
+ } else {
+ ide_abort_command(s);
+ }
+ ide_set_irq(s);
+ break;
+ case WIN_SRST:
+ if (!s->is_cdrom)
+ goto abort_cmd;
+ ide_set_signature(s);
+ s->status = 0x00; /* NOTE: READY is _not_ set */
+ s->error = 0x01;
+ break;
+ case WIN_PACKETCMD:
+ if (!s->is_cdrom)
+ goto abort_cmd;
+ /* overlapping commands not supported */
+ if (s->feature & 0x02)
+ goto abort_cmd;
+ s->atapi_dma = s->feature & 1;
+ s->nsector = 1;
+ ide_transfer_start(s, s->io_buffer, ATAPI_PACKET_SIZE,
+ ide_atapi_cmd);
+ break;
+ default:
+ abort_cmd:
+ ide_abort_command(s);
+ ide_set_irq(s);
+ break;
+ }
+ }
+}
+
+static uint32_t ide_ioport_read(void *opaque, uint32_t addr1)
+{
+ IDEState *ide_if = opaque;
+ IDEState *s = ide_if->cur_drive;
+ uint32_t addr;
+ int ret;
+
+ addr = addr1 & 7;
+ switch(addr) {
+ case 0:
+ ret = 0xff;
+ break;
+ case 1:
+ if (!ide_if[0].bs && !ide_if[1].bs)
+ ret = 0;
+ else
+ ret = s->error;
+ break;
+ case 2:
+ if (!ide_if[0].bs && !ide_if[1].bs)
+ ret = 0;
+ else
+ ret = s->nsector & 0xff;
+ break;
+ case 3:
+ if (!ide_if[0].bs && !ide_if[1].bs)
+ ret = 0;
+ else
+ ret = s->sector;
+ break;
+ case 4:
+ if (!ide_if[0].bs && !ide_if[1].bs)
+ ret = 0;
+ else
+ ret = s->lcyl;
+ break;
+ case 5:
+ if (!ide_if[0].bs && !ide_if[1].bs)
+ ret = 0;
+ else
+ ret = s->hcyl;
+ break;
+ case 6:
+ if (!ide_if[0].bs && !ide_if[1].bs)
+ ret = 0;
+ else
+ ret = s->select;
+ break;
+ default:
+ case 7:
+ if ((!ide_if[0].bs && !ide_if[1].bs) ||
+ (s != ide_if && !s->bs))
+ ret = 0;
+ else
+ ret = s->status;
+#ifdef TARGET_PPC
+ if (s->openpic)
+ openpic_set_irq(s->openpic, s->irq, 0);
+ else
+#endif
+ if (s->irq == 16)
+ pci_set_irq(s->pci_dev, 0, 0);
+ else
+ pic_set_irq(s->irq, 0);
+ break;
+ }
+#ifdef DEBUG_IDE
+ printf("ide: read addr=0x%x val=%02x\n", addr1, ret);
+#endif
+ return ret;
+}
+
+static uint32_t ide_status_read(void *opaque, uint32_t addr)
+{
+ IDEState *ide_if = opaque;
+ IDEState *s = ide_if->cur_drive;
+ int ret;
+
+ if ((!ide_if[0].bs && !ide_if[1].bs) ||
+ (s != ide_if && !s->bs))
+ ret = 0;
+ else
+ ret = s->status;
+#ifdef DEBUG_IDE
+ printf("ide: read status addr=0x%x val=%02x\n", addr, ret);
+#endif
+ return ret;
+}
+
+static void ide_cmd_write(void *opaque, uint32_t addr, uint32_t val)
+{
+ IDEState *ide_if = opaque;
+ IDEState *s;
+ int i;
+
+#ifdef DEBUG_IDE
+ printf("ide: write control addr=0x%x val=%02x\n", addr, val);
+#endif
+ /* common for both drives */
+ if (!(ide_if[0].cmd & IDE_CMD_RESET) &&
+ (val & IDE_CMD_RESET)) {
+ /* reset low to high */
+ for(i = 0;i < 2; i++) {
+ s = &ide_if[i];
+ s->status = BUSY_STAT | SEEK_STAT;
+ s->error = 0x01;
+ }
+ } else if ((ide_if[0].cmd & IDE_CMD_RESET) &&
+ !(val & IDE_CMD_RESET)) {
+ /* high to low */
+ for(i = 0;i < 2; i++) {
+ s = &ide_if[i];
+ if (s->is_cdrom)
+ s->status = 0x00; /* NOTE: READY is _not_ set */
+ else
+ s->status = READY_STAT | SEEK_STAT;
+ ide_set_signature(s);
+ }
+ }
+
+ ide_if[0].cmd = val;
+ ide_if[1].cmd = val;
+}
+
+static void ide_data_writew(void *opaque, uint32_t addr, uint32_t val)
+{
+ IDEState *s = ((IDEState *)opaque)->cur_drive;
+ uint8_t *p;
+
+ p = s->data_ptr;
+ *(uint16_t *)p = le16_to_cpu(val);
+ p += 2;
+ s->data_ptr = p;
+ if (p >= s->data_end)
+ s->end_transfer_func(s);
+}
+
+static uint32_t ide_data_readw(void *opaque, uint32_t addr)
+{
+ IDEState *s = ((IDEState *)opaque)->cur_drive;
+ uint8_t *p;
+ int ret;
+ p = s->data_ptr;
+ ret = cpu_to_le16(*(uint16_t *)p);
+ p += 2;
+ s->data_ptr = p;
+ if (p >= s->data_end)
+ s->end_transfer_func(s);
+ return ret;
+}
+
+static void ide_data_writel(void *opaque, uint32_t addr, uint32_t val)
+{
+ IDEState *s = ((IDEState *)opaque)->cur_drive;
+ uint8_t *p;
+
+ p = s->data_ptr;
+ *(uint32_t *)p = le32_to_cpu(val);
+ p += 4;
+ s->data_ptr = p;
+ if (p >= s->data_end)
+ s->end_transfer_func(s);
+}
+
+static uint32_t ide_data_readl(void *opaque, uint32_t addr)
+{
+ IDEState *s = ((IDEState *)opaque)->cur_drive;
+ uint8_t *p;
+ int ret;
+
+ p = s->data_ptr;
+ ret = cpu_to_le32(*(uint32_t *)p);
+ p += 4;
+ s->data_ptr = p;
+ if (p >= s->data_end)
+ s->end_transfer_func(s);
+ return ret;
+}
+
+static void ide_dummy_transfer_stop(IDEState *s)
+{
+ s->data_ptr = s->io_buffer;
+ s->data_end = s->io_buffer;
+ s->io_buffer[0] = 0xff;
+ s->io_buffer[1] = 0xff;
+ s->io_buffer[2] = 0xff;
+ s->io_buffer[3] = 0xff;
+}
+
+static void ide_reset(IDEState *s)
+{
+ s->mult_sectors = MAX_MULT_SECTORS;
+ s->cur_drive = s;
+ s->select = 0xa0;
+ s->status = READY_STAT;
+ ide_set_signature(s);
+ /* init the transfer handler so that 0xffff is returned on data
+ accesses */
+ s->end_transfer_func = ide_dummy_transfer_stop;
+ ide_dummy_transfer_stop(s);
+}
+
+struct partition {
+ uint8_t boot_ind; /* 0x80 - active */
+ uint8_t head; /* starting head */
+ uint8_t sector; /* starting sector */
+ uint8_t cyl; /* starting cylinder */
+ uint8_t sys_ind; /* What partition type */
+ uint8_t end_head; /* end head */
+ uint8_t end_sector; /* end sector */
+ uint8_t end_cyl; /* end cylinder */
+ uint32_t start_sect; /* starting sector counting from 0 */
+ uint32_t nr_sects; /* nr of sectors in partition */
+} __attribute__((packed));
+
+/* try to guess the IDE geometry from the MSDOS partition table */
+static void ide_guess_geometry(IDEState *s)
+{
+ uint8_t buf[512];
+ int ret, i;
+ struct partition *p;
+ uint32_t nr_sects;
+
+ if (s->cylinders != 0)
+ return;
+ ret = bdrv_read(s->bs, 0, buf, 1);
+ if (ret < 0)
+ return;
+ /* test msdos magic */
+ if (buf[510] != 0x55 || buf[511] != 0xaa)
+ return;
+ for(i = 0; i < 4; i++) {
+ p = ((struct partition *)(buf + 0x1be)) + i;
+ nr_sects = le32_to_cpu(p->nr_sects);
+ if (nr_sects && p->end_head) {
+ /* We make the assumption that the partition terminates on
+ a cylinder boundary */
+ s->heads = p->end_head + 1;
+ s->sectors = p->end_sector & 63;
+ s->cylinders = s->nb_sectors / (s->heads * s->sectors);
+#if 0
+ printf("guessed partition: CHS=%d %d %d\n",
+ s->cylinders, s->heads, s->sectors);
+#endif
+ }
+ }
+}
+
+static void ide_init2(IDEState *ide_state, int irq,
+ BlockDriverState *hd0, BlockDriverState *hd1)
+{
+ IDEState *s;
+ static int drive_serial = 1;
+ int i, cylinders, heads, secs;
+ int64_t nb_sectors;
+
+ for(i = 0; i < 2; i++) {
+ s = ide_state + i;
+ if (i == 0)
+ s->bs = hd0;
+ else
+ s->bs = hd1;
+ if (s->bs) {
+ bdrv_get_geometry(s->bs, &nb_sectors);
+ s->nb_sectors = nb_sectors;
+ /* if a geometry hint is available, use it */
+ bdrv_get_geometry_hint(s->bs, &cylinders, &heads, &secs);
+ if (cylinders != 0) {
+ s->cylinders = cylinders;
+ s->heads = heads;
+ s->sectors = secs;
+ } else {
+ ide_guess_geometry(s);
+ if (s->cylinders == 0) {
+ /* if no geometry, use a LBA compatible one */
+ cylinders = nb_sectors / (16 * 63);
+ if (cylinders > 16383)
+ cylinders = 16383;
+ else if (cylinders < 2)
+ cylinders = 2;
+ s->cylinders = cylinders;
+ s->heads = 16;
+ s->sectors = 63;
+ }
+ bdrv_set_geometry_hint(s->bs, s->cylinders, s->heads, s->sectors);
+ }
+ if (bdrv_get_type_hint(s->bs) == BDRV_TYPE_CDROM) {
+ s->is_cdrom = 1;
+ bdrv_set_change_cb(s->bs, cdrom_change_cb, s);
+ }
+ }
+ s->drive_serial = drive_serial++;
+ s->irq = irq;
+ ide_reset(s);
+ }
+}
+
+static void ide_init_ioport(IDEState *ide_state, int iobase, int iobase2)
+{
+ register_ioport_write(iobase, 8, 1, ide_ioport_write, ide_state);
+ register_ioport_read(iobase, 8, 1, ide_ioport_read, ide_state);
+ if (iobase2) {
+ register_ioport_read(iobase2, 1, 1, ide_status_read, ide_state);
+ register_ioport_write(iobase2, 1, 1, ide_cmd_write, ide_state);
+ }
+
+ /* data ports */
+ register_ioport_write(iobase, 2, 2, ide_data_writew, ide_state);
+ register_ioport_read(iobase, 2, 2, ide_data_readw, ide_state);
+ register_ioport_write(iobase, 4, 4, ide_data_writel, ide_state);
+ register_ioport_read(iobase, 4, 4, ide_data_readl, ide_state);
+}
+
+/***********************************************************/
+/* ISA IDE definitions */
+
+void isa_ide_init(int iobase, int iobase2, int irq,
+ BlockDriverState *hd0, BlockDriverState *hd1)
+{
+ IDEState *ide_state;
+
+ ide_state = qemu_mallocz(sizeof(IDEState) * 2);
+ if (!ide_state)
+ return;
+
+ ide_init2(ide_state, irq, hd0, hd1);
+ ide_init_ioport(ide_state, iobase, iobase2);
+}
+
+/***********************************************************/
+/* PCI IDE definitions */
+
+static void ide_map(PCIDevice *pci_dev, int region_num,
+ uint32_t addr, uint32_t size, int type)
+{
+ PCIIDEState *d = (PCIIDEState *)pci_dev;
+ IDEState *ide_state;
+
+ if (region_num <= 3) {
+ ide_state = &d->ide_if[(region_num >> 1) * 2];
+ if (region_num & 1) {
+ register_ioport_read(addr + 2, 1, 1, ide_status_read, ide_state);
+ register_ioport_write(addr + 2, 1, 1, ide_cmd_write, ide_state);
+ } else {
+ register_ioport_write(addr, 8, 1, ide_ioport_write, ide_state);
+ register_ioport_read(addr, 8, 1, ide_ioport_read, ide_state);
+
+ /* data ports */
+ register_ioport_write(addr, 2, 2, ide_data_writew, ide_state);
+ register_ioport_read(addr, 2, 2, ide_data_readw, ide_state);
+ register_ioport_write(addr, 4, 4, ide_data_writel, ide_state);
+ register_ioport_read(addr, 4, 4, ide_data_readl, ide_state);
+ }
+ }
+}
+
+/* XXX: full callback usage to prepare non blocking I/Os support -
+ error handling */
+static void ide_dma_loop(BMDMAState *bm)
+{
+ struct {
+ uint32_t addr;
+ uint32_t size;
+ } prd;
+ target_phys_addr_t cur_addr;
+ int len, i, len1;
+
+ cur_addr = bm->addr;
+ /* at most one page to avoid hanging if erroneous parameters */
+ for(i = 0; i < 512; i++) {
+ cpu_physical_memory_read(cur_addr, (uint8_t *)&prd, 8);
+ prd.addr = le32_to_cpu(prd.addr);
+ prd.size = le32_to_cpu(prd.size);
+#ifdef DEBUG_IDE
+ printf("ide: dma: prd: %08x: addr=0x%08x size=0x%08x\n",
+ (int)cur_addr, prd.addr, prd.size);
+#endif
+ len = prd.size & 0xfffe;
+ if (len == 0)
+ len = 0x10000;
+ while (len > 0) {
+ len1 = bm->dma_cb(bm->ide_if, prd.addr, len);
+ if (len1 == 0)
+ goto the_end;
+ prd.addr += len1;
+ len -= len1;
+ }
+ /* end of transfer */
+ if (prd.size & 0x80000000)
+ break;
+ cur_addr += 8;
+ }
+ /* end of transfer */
+ the_end:
+ bm->status &= ~BM_STATUS_DMAING;
+ bm->status |= BM_STATUS_INT;
+ bm->dma_cb = NULL;
+ bm->ide_if = NULL;
+}
+
+static void ide_dma_start(IDEState *s, IDEDMAFunc *dma_cb)
+{
+ BMDMAState *bm = s->bmdma;
+ if(!bm)
+ return;
+ bm->ide_if = s;
+ bm->dma_cb = dma_cb;
+ if (bm->status & BM_STATUS_DMAING) {
+ ide_dma_loop(bm);
+ }
+}
+
+static uint32_t bmdma_cmd_readb(void *opaque, uint32_t addr)
+{
+ BMDMAState *bm = opaque;
+ uint32_t val;
+ val = bm->cmd;
+#ifdef DEBUG_IDE
+ printf("%s: 0x%08x\n", __func__, val);
+#endif
+ return val;
+}
+
+static void bmdma_cmd_writeb(void *opaque, uint32_t addr, uint32_t val)
+{
+ BMDMAState *bm = opaque;
+#ifdef DEBUG_IDE
+ printf("%s: 0x%08x\n", __func__, val);
+#endif
+ if (!(val & BM_CMD_START)) {
+ /* XXX: do it better */
+ bm->status &= ~BM_STATUS_DMAING;
+ bm->cmd = val & 0x09;
+ } else {
+ bm->status |= BM_STATUS_DMAING;
+ bm->cmd = val & 0x09;
+ /* start dma transfer if possible */
+ if (bm->dma_cb)
+ ide_dma_loop(bm);
+ }
+}
+
+static uint32_t bmdma_status_readb(void *opaque, uint32_t addr)
+{
+ BMDMAState *bm = opaque;
+ uint32_t val;
+ val = bm->status;
+#ifdef DEBUG_IDE
+ printf("%s: 0x%08x\n", __func__, val);
+#endif
+ return val;
+}
+
+static void bmdma_status_writeb(void *opaque, uint32_t addr, uint32_t val)
+{
+ BMDMAState *bm = opaque;
+#ifdef DEBUG_IDE
+ printf("%s: 0x%08x\n", __func__, val);
+#endif
+ bm->status = (val & 0x60) | (bm->status & 1) | (bm->status & ~val & 0x06);
+}
+
+static uint32_t bmdma_addr_readl(void *opaque, uint32_t addr)
+{
+ BMDMAState *bm = opaque;
+ uint32_t val;
+ val = bm->addr;
+#ifdef DEBUG_IDE
+ printf("%s: 0x%08x\n", __func__, val);
+#endif
+ return val;
+}
+
+static void bmdma_addr_writel(void *opaque, uint32_t addr, uint32_t val)
+{
+ BMDMAState *bm = opaque;
+#ifdef DEBUG_IDE
+ printf("%s: 0x%08x\n", __func__, val);
+#endif
+ bm->addr = val & ~3;
+}
+
+static void bmdma_map(PCIDevice *pci_dev, int region_num,
+ uint32_t addr, uint32_t size, int type)
+{
+ PCIIDEState *d = (PCIIDEState *)pci_dev;
+ int i;
+
+ for(i = 0;i < 2; i++) {
+ BMDMAState *bm = &d->bmdma[i];
+ d->ide_if[2 * i].bmdma = bm;
+ d->ide_if[2 * i + 1].bmdma = bm;
+
+ register_ioport_write(addr, 1, 1, bmdma_cmd_writeb, bm);
+ register_ioport_read(addr, 1, 1, bmdma_cmd_readb, bm);
+
+ register_ioport_write(addr + 2, 1, 1, bmdma_status_writeb, bm);
+ register_ioport_read(addr + 2, 1, 1, bmdma_status_readb, bm);
+
+ register_ioport_write(addr + 4, 4, 4, bmdma_addr_writel, bm);
+ register_ioport_read(addr + 4, 4, 4, bmdma_addr_readl, bm);
+ addr += 8;
+ }
+}
+
+/* hd_table must contain 4 block drivers */
+void pci_ide_init(PCIBus *bus, BlockDriverState **hd_table)
+{
+ PCIIDEState *d;
+ uint8_t *pci_conf;
+ int i;
+
+ d = (PCIIDEState *)pci_register_device(bus, "IDE", sizeof(PCIIDEState),
+ -1,
+ NULL, NULL);
+ pci_conf = d->dev.config;
+ pci_conf[0x00] = 0x86; // Intel
+ pci_conf[0x01] = 0x80;
+ pci_conf[0x02] = 0x00; // fake
+ pci_conf[0x03] = 0x01; // fake
+ pci_conf[0x0a] = 0x01; // class_sub = PCI_IDE
+ pci_conf[0x0b] = 0x01; // class_base = PCI_mass_storage
+ pci_conf[0x0e] = 0x80; // header_type = PCI_multifunction, generic
+
+ pci_conf[0x2c] = 0x86; // subsys vendor
+ pci_conf[0x2d] = 0x80; // subsys vendor
+ pci_conf[0x2e] = 0x00; // fake
+ pci_conf[0x2f] = 0x01; // fake
+
+ pci_register_io_region((PCIDevice *)d, 0, 0x8,
+ PCI_ADDRESS_SPACE_IO, ide_map);
+ pci_register_io_region((PCIDevice *)d, 1, 0x4,
+ PCI_ADDRESS_SPACE_IO, ide_map);
+ pci_register_io_region((PCIDevice *)d, 2, 0x8,
+ PCI_ADDRESS_SPACE_IO, ide_map);
+ pci_register_io_region((PCIDevice *)d, 3, 0x4,
+ PCI_ADDRESS_SPACE_IO, ide_map);
+ pci_register_io_region((PCIDevice *)d, 4, 0x10,
+ PCI_ADDRESS_SPACE_IO, bmdma_map);
+
+ pci_conf[0x3d] = 0x01; // interrupt on pin 1
+
+ for(i = 0; i < 4; i++)
+ d->ide_if[i].pci_dev = (PCIDevice *)d;
+ ide_init2(&d->ide_if[0], 16, hd_table[0], hd_table[1]);
+ ide_init2(&d->ide_if[2], 16, hd_table[2], hd_table[3]);
+}
+
+/* hd_table must contain 4 block drivers */
+/* NOTE: for the PIIX3, the IRQs and IOports are hardcoded */
+void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table)
+{
+ PCIIDEState *d;
+ uint8_t *pci_conf;
+
+ /* register a function 1 of PIIX3 */
+ d = (PCIIDEState *)pci_register_device(bus, "PIIX3 IDE",
+ sizeof(PCIIDEState),
+ ((PCIDevice *)piix3_state)->devfn + 1,
+ NULL, NULL);
+ pci_conf = d->dev.config;
+ pci_conf[0x00] = 0x86; // Intel
+ pci_conf[0x01] = 0x80;
+ pci_conf[0x02] = 0x10;
+ pci_conf[0x03] = 0x70;
+ pci_conf[0x0a] = 0x01; // class_sub = PCI_IDE
+ pci_conf[0x0b] = 0x01; // class_base = PCI_mass_storage
+ pci_conf[0x0e] = 0x00; // header_type
+
+ pci_register_io_region((PCIDevice *)d, 4, 0x10,
+ PCI_ADDRESS_SPACE_IO, bmdma_map);
+
+ ide_init2(&d->ide_if[0], 14, hd_table[0], hd_table[1]);
+ ide_init2(&d->ide_if[2], 15, hd_table[2], hd_table[3]);
+ ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6);
+ ide_init_ioport(&d->ide_if[2], 0x170, 0x376);
+}
+
+/***********************************************************/
+/* MacIO based PowerPC IDE */
+
+/* PowerMac IDE memory IO */
+static void pmac_ide_writeb (void *opaque,
+ target_phys_addr_t addr, uint32_t val)
+{
+ addr = (addr & 0xFFF) >> 4;
+ switch (addr) {
+ case 1 ... 7:
+ ide_ioport_write(opaque, addr, val);
+ break;
+ case 8:
+ case 22:
+ ide_cmd_write(opaque, 0, val);
+ break;
+ default:
+ break;
+ }
+}
+
+static uint32_t pmac_ide_readb (void *opaque,target_phys_addr_t addr)
+{
+ uint8_t retval;
+
+ addr = (addr & 0xFFF) >> 4;
+ switch (addr) {
+ case 1 ... 7:
+ retval = ide_ioport_read(opaque, addr);
+ break;
+ case 8:
+ case 22:
+ retval = ide_status_read(opaque, 0);
+ break;
+ default:
+ retval = 0xFF;
+ break;
+ }
+ return retval;
+}
+
+static void pmac_ide_writew (void *opaque,
+ target_phys_addr_t addr, uint32_t val)
+{
+ addr = (addr & 0xFFF) >> 4;
+#ifdef TARGET_WORDS_BIGENDIAN
+ val = bswap16(val);
+#endif
+ if (addr == 0) {
+ ide_data_writew(opaque, 0, val);
+ }
+}
+
+static uint32_t pmac_ide_readw (void *opaque,target_phys_addr_t addr)
+{
+ uint16_t retval;
+
+ addr = (addr & 0xFFF) >> 4;
+ if (addr == 0) {
+ retval = ide_data_readw(opaque, 0);
+ } else {
+ retval = 0xFFFF;
+ }
+#ifdef TARGET_WORDS_BIGENDIAN
+ retval = bswap16(retval);
+#endif
+ return retval;
+}
+
+static void pmac_ide_writel (void *opaque,
+ target_phys_addr_t addr, uint32_t val)
+{
+ addr = (addr & 0xFFF) >> 4;
+#ifdef TARGET_WORDS_BIGENDIAN
+ val = bswap32(val);
+#endif
+ if (addr == 0) {
+ ide_data_writel(opaque, 0, val);
+ }
+}
+
+static uint32_t pmac_ide_readl (void *opaque,target_phys_addr_t addr)
+{
+ uint32_t retval;
+
+ addr = (addr & 0xFFF) >> 4;
+ if (addr == 0) {
+ retval = ide_data_readl(opaque, 0);
+ } else {
+ retval = 0xFFFFFFFF;
+ }
+#ifdef TARGET_WORDS_BIGENDIAN
+ retval = bswap32(retval);
+#endif
+ return retval;
+}
+
+static CPUWriteMemoryFunc *pmac_ide_write[] = {
+ pmac_ide_writeb,
+ pmac_ide_writew,
+ pmac_ide_writel,
+};
+
+static CPUReadMemoryFunc *pmac_ide_read[] = {
+ pmac_ide_readb,
+ pmac_ide_readw,
+ pmac_ide_readl,
+};
+
+/* hd_table must contain 4 block drivers */
+/* PowerMac uses memory mapped registers, not I/O. Return the memory
+ I/O index to access the ide. */
+int pmac_ide_init (BlockDriverState **hd_table,
+ openpic_t *openpic, int irq)
+{
+ IDEState *ide_if;
+ int pmac_ide_memory;
+
+ ide_if = qemu_mallocz(sizeof(IDEState) * 2);
+ ide_init2(&ide_if[0], irq, hd_table[0], hd_table[1]);
+ ide_if[0].openpic = openpic;
+ ide_if[1].openpic = openpic;
+
+ pmac_ide_memory = cpu_register_io_memory(0, pmac_ide_read,
+ pmac_ide_write, &ide_if[0]);
+ return pmac_ide_memory;
+}
--- /dev/null
+/*
+ * QEMU SPARC iommu emulation
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+
+/* debug iommu */
+//#define DEBUG_IOMMU
+
+/* The IOMMU registers occupy three pages in IO space. */
+struct iommu_regs {
+ /* First page */
+ volatile unsigned long control; /* IOMMU control */
+ volatile unsigned long base; /* Physical base of iopte page table */
+ volatile unsigned long _unused1[3];
+ volatile unsigned long tlbflush; /* write only */
+ volatile unsigned long pageflush; /* write only */
+ volatile unsigned long _unused2[1017];
+ /* Second page */
+ volatile unsigned long afsr; /* Async-fault status register */
+ volatile unsigned long afar; /* Async-fault physical address */
+ volatile unsigned long _unused3[2];
+ volatile unsigned long sbuscfg0; /* SBUS configuration registers, per-slot */
+ volatile unsigned long sbuscfg1;
+ volatile unsigned long sbuscfg2;
+ volatile unsigned long sbuscfg3;
+ volatile unsigned long mfsr; /* Memory-fault status register */
+ volatile unsigned long mfar; /* Memory-fault physical address */
+ volatile unsigned long _unused4[1014];
+ /* Third page */
+ volatile unsigned long mid; /* IOMMU module-id */
+};
+
+#define IOMMU_CTRL_IMPL 0xf0000000 /* Implementation */
+#define IOMMU_CTRL_VERS 0x0f000000 /* Version */
+#define IOMMU_CTRL_RNGE 0x0000001c /* Mapping RANGE */
+#define IOMMU_RNGE_16MB 0x00000000 /* 0xff000000 -> 0xffffffff */
+#define IOMMU_RNGE_32MB 0x00000004 /* 0xfe000000 -> 0xffffffff */
+#define IOMMU_RNGE_64MB 0x00000008 /* 0xfc000000 -> 0xffffffff */
+#define IOMMU_RNGE_128MB 0x0000000c /* 0xf8000000 -> 0xffffffff */
+#define IOMMU_RNGE_256MB 0x00000010 /* 0xf0000000 -> 0xffffffff */
+#define IOMMU_RNGE_512MB 0x00000014 /* 0xe0000000 -> 0xffffffff */
+#define IOMMU_RNGE_1GB 0x00000018 /* 0xc0000000 -> 0xffffffff */
+#define IOMMU_RNGE_2GB 0x0000001c /* 0x80000000 -> 0xffffffff */
+#define IOMMU_CTRL_ENAB 0x00000001 /* IOMMU Enable */
+
+#define IOMMU_AFSR_ERR 0x80000000 /* LE, TO, or BE asserted */
+#define IOMMU_AFSR_LE 0x40000000 /* SBUS reports error after transaction */
+#define IOMMU_AFSR_TO 0x20000000 /* Write access took more than 12.8 us. */
+#define IOMMU_AFSR_BE 0x10000000 /* Write access received error acknowledge */
+#define IOMMU_AFSR_SIZE 0x0e000000 /* Size of transaction causing error */
+#define IOMMU_AFSR_S 0x01000000 /* Sparc was in supervisor mode */
+#define IOMMU_AFSR_RESV 0x00f00000 /* Reserver, forced to 0x8 by hardware */
+#define IOMMU_AFSR_ME 0x00080000 /* Multiple errors occurred */
+#define IOMMU_AFSR_RD 0x00040000 /* A read operation was in progress */
+#define IOMMU_AFSR_FAV 0x00020000 /* IOMMU afar has valid contents */
+
+#define IOMMU_SBCFG_SAB30 0x00010000 /* Phys-address bit 30 when bypass enabled */
+#define IOMMU_SBCFG_BA16 0x00000004 /* Slave supports 16 byte bursts */
+#define IOMMU_SBCFG_BA8 0x00000002 /* Slave supports 8 byte bursts */
+#define IOMMU_SBCFG_BYPASS 0x00000001 /* Bypass IOMMU, treat all addresses
+ produced by this device as pure
+ physical. */
+
+#define IOMMU_MFSR_ERR 0x80000000 /* One or more of PERR1 or PERR0 */
+#define IOMMU_MFSR_S 0x01000000 /* Sparc was in supervisor mode */
+#define IOMMU_MFSR_CPU 0x00800000 /* CPU transaction caused parity error */
+#define IOMMU_MFSR_ME 0x00080000 /* Multiple parity errors occurred */
+#define IOMMU_MFSR_PERR 0x00006000 /* high bit indicates parity error occurred
+ on the even word of the access, low bit
+ indicated odd word caused the parity error */
+#define IOMMU_MFSR_BM 0x00001000 /* Error occurred while in boot mode */
+#define IOMMU_MFSR_C 0x00000800 /* Address causing error was marked cacheable */
+#define IOMMU_MFSR_RTYP 0x000000f0 /* Memory request transaction type */
+
+#define IOMMU_MID_SBAE 0x001f0000 /* SBus arbitration enable */
+#define IOMMU_MID_SE 0x00100000 /* Enables SCSI/ETHERNET arbitration */
+#define IOMMU_MID_SB3 0x00080000 /* Enable SBUS device 3 arbitration */
+#define IOMMU_MID_SB2 0x00040000 /* Enable SBUS device 2 arbitration */
+#define IOMMU_MID_SB1 0x00020000 /* Enable SBUS device 1 arbitration */
+#define IOMMU_MID_SB0 0x00010000 /* Enable SBUS device 0 arbitration */
+#define IOMMU_MID_MID 0x0000000f /* Module-id, hardcoded to 0x8 */
+
+/* The format of an iopte in the page tables */
+#define IOPTE_PAGE 0x07ffff00 /* Physical page number (PA[30:12]) */
+#define IOPTE_CACHE 0x00000080 /* Cached (in vme IOCACHE or Viking/MXCC) */
+#define IOPTE_WRITE 0x00000004 /* Writeable */
+#define IOPTE_VALID 0x00000002 /* IOPTE is valid */
+#define IOPTE_WAZ 0x00000001 /* Write as zeros */
+
+#define PAGE_SHIFT 12
+#define PAGE_SIZE (1 << PAGE_SHIFT)
+#define PAGE_MASK (PAGE_SIZE - 1)
+
+typedef struct IOMMUState {
+ uint32_t addr;
+ uint32_t regs[sizeof(struct iommu_regs)];
+ uint32_t iostart;
+} IOMMUState;
+
+static IOMMUState *ps;
+
+static uint32_t iommu_mem_readw(void *opaque, target_phys_addr_t addr)
+{
+ IOMMUState *s = opaque;
+ uint32_t saddr;
+
+ saddr = (addr - s->addr) >> 2;
+ switch (saddr) {
+ default:
+ return s->regs[saddr];
+ break;
+ }
+ return 0;
+}
+
+static void iommu_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ IOMMUState *s = opaque;
+ uint32_t saddr;
+
+ saddr = (addr - s->addr) >> 2;
+ switch (saddr) {
+ case 0:
+ switch (val & IOMMU_CTRL_RNGE) {
+ case IOMMU_RNGE_16MB:
+ s->iostart = 0xff000000;
+ break;
+ case IOMMU_RNGE_32MB:
+ s->iostart = 0xfe000000;
+ break;
+ case IOMMU_RNGE_64MB:
+ s->iostart = 0xfc000000;
+ break;
+ case IOMMU_RNGE_128MB:
+ s->iostart = 0xf8000000;
+ break;
+ case IOMMU_RNGE_256MB:
+ s->iostart = 0xf0000000;
+ break;
+ case IOMMU_RNGE_512MB:
+ s->iostart = 0xe0000000;
+ break;
+ case IOMMU_RNGE_1GB:
+ s->iostart = 0xc0000000;
+ break;
+ default:
+ case IOMMU_RNGE_2GB:
+ s->iostart = 0x80000000;
+ break;
+ }
+ /* Fall through */
+ default:
+ s->regs[saddr] = val;
+ break;
+ }
+}
+
+static CPUReadMemoryFunc *iommu_mem_read[3] = {
+ iommu_mem_readw,
+ iommu_mem_readw,
+ iommu_mem_readw,
+};
+
+static CPUWriteMemoryFunc *iommu_mem_write[3] = {
+ iommu_mem_writew,
+ iommu_mem_writew,
+ iommu_mem_writew,
+};
+
+uint32_t iommu_translate(uint32_t addr)
+{
+ uint32_t *iopte = (void *)(ps->regs[1] << 4), pa;
+
+ iopte += ((addr - ps->iostart) >> PAGE_SHIFT);
+ cpu_physical_memory_rw((uint32_t)iopte, (void *) &pa, 4, 0);
+ bswap32s(&pa);
+ pa = (pa & IOPTE_PAGE) << 4; /* Loose higher bits of 36 */
+ return pa + (addr & PAGE_MASK);
+}
+
+void iommu_init(uint32_t addr)
+{
+ IOMMUState *s;
+ int iommu_io_memory;
+
+ s = qemu_mallocz(sizeof(IOMMUState));
+ if (!s)
+ return;
+
+ s->addr = addr;
+
+ iommu_io_memory = cpu_register_io_memory(0, iommu_mem_read, iommu_mem_write, s);
+ cpu_register_physical_memory(addr, sizeof(struct iommu_regs),
+ iommu_io_memory);
+
+ ps = s;
+}
+
--- /dev/null
+/*
+ * QEMU Lance emulation
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+
+/* debug LANCE card */
+//#define DEBUG_LANCE
+
+#ifndef LANCE_LOG_TX_BUFFERS
+#define LANCE_LOG_TX_BUFFERS 4
+#define LANCE_LOG_RX_BUFFERS 4
+#endif
+
+#define CRC_POLYNOMIAL_BE 0x04c11db7UL /* Ethernet CRC, big endian */
+#define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */
+
+
+#define LE_CSR0 0
+#define LE_CSR1 1
+#define LE_CSR2 2
+#define LE_CSR3 3
+#define LE_MAXREG (LE_CSR3 + 1)
+
+#define LE_RDP 0
+#define LE_RAP 1
+
+#define LE_MO_PROM 0x8000 /* Enable promiscuous mode */
+
+#define LE_C0_ERR 0x8000 /* Error: set if BAB, SQE, MISS or ME is set */
+#define LE_C0_BABL 0x4000 /* BAB: Babble: tx timeout. */
+#define LE_C0_CERR 0x2000 /* SQE: Signal quality error */
+#define LE_C0_MISS 0x1000 /* MISS: Missed a packet */
+#define LE_C0_MERR 0x0800 /* ME: Memory error */
+#define LE_C0_RINT 0x0400 /* Received interrupt */
+#define LE_C0_TINT 0x0200 /* Transmitter Interrupt */
+#define LE_C0_IDON 0x0100 /* IFIN: Init finished. */
+#define LE_C0_INTR 0x0080 /* Interrupt or error */
+#define LE_C0_INEA 0x0040 /* Interrupt enable */
+#define LE_C0_RXON 0x0020 /* Receiver on */
+#define LE_C0_TXON 0x0010 /* Transmitter on */
+#define LE_C0_TDMD 0x0008 /* Transmitter demand */
+#define LE_C0_STOP 0x0004 /* Stop the card */
+#define LE_C0_STRT 0x0002 /* Start the card */
+#define LE_C0_INIT 0x0001 /* Init the card */
+
+#define LE_C3_BSWP 0x4 /* SWAP */
+#define LE_C3_ACON 0x2 /* ALE Control */
+#define LE_C3_BCON 0x1 /* Byte control */
+
+/* Receive message descriptor 1 */
+#define LE_R1_OWN 0x80 /* Who owns the entry */
+#define LE_R1_ERR 0x40 /* Error: if FRA, OFL, CRC or BUF is set */
+#define LE_R1_FRA 0x20 /* FRA: Frame error */
+#define LE_R1_OFL 0x10 /* OFL: Frame overflow */
+#define LE_R1_CRC 0x08 /* CRC error */
+#define LE_R1_BUF 0x04 /* BUF: Buffer error */
+#define LE_R1_SOP 0x02 /* Start of packet */
+#define LE_R1_EOP 0x01 /* End of packet */
+#define LE_R1_POK 0x03 /* Packet is complete: SOP + EOP */
+
+#define LE_T1_OWN 0x80 /* Lance owns the packet */
+#define LE_T1_ERR 0x40 /* Error summary */
+#define LE_T1_EMORE 0x10 /* Error: more than one retry needed */
+#define LE_T1_EONE 0x08 /* Error: one retry needed */
+#define LE_T1_EDEF 0x04 /* Error: deferred */
+#define LE_T1_SOP 0x02 /* Start of packet */
+#define LE_T1_EOP 0x01 /* End of packet */
+#define LE_T1_POK 0x03 /* Packet is complete: SOP + EOP */
+
+#define LE_T3_BUF 0x8000 /* Buffer error */
+#define LE_T3_UFL 0x4000 /* Error underflow */
+#define LE_T3_LCOL 0x1000 /* Error late collision */
+#define LE_T3_CLOS 0x0800 /* Error carrier loss */
+#define LE_T3_RTY 0x0400 /* Error retry */
+#define LE_T3_TDR 0x03ff /* Time Domain Reflectometry counter */
+
+#define TX_RING_SIZE (1 << (LANCE_LOG_TX_BUFFERS))
+#define TX_RING_MOD_MASK (TX_RING_SIZE - 1)
+#define TX_RING_LEN_BITS ((LANCE_LOG_TX_BUFFERS) << 29)
+
+#define RX_RING_SIZE (1 << (LANCE_LOG_RX_BUFFERS))
+#define RX_RING_MOD_MASK (RX_RING_SIZE - 1)
+#define RX_RING_LEN_BITS ((LANCE_LOG_RX_BUFFERS) << 29)
+
+#define PKT_BUF_SZ 1544
+#define RX_BUFF_SIZE PKT_BUF_SZ
+#define TX_BUFF_SIZE PKT_BUF_SZ
+
+struct lance_rx_desc {
+ unsigned short rmd0; /* low address of packet */
+ unsigned char rmd1_bits; /* descriptor bits */
+ unsigned char rmd1_hadr; /* high address of packet */
+ short length; /* This length is 2s complement (negative)!
+ * Buffer length
+ */
+ unsigned short mblength; /* This is the actual number of bytes received */
+};
+
+struct lance_tx_desc {
+ unsigned short tmd0; /* low address of packet */
+ unsigned char tmd1_bits; /* descriptor bits */
+ unsigned char tmd1_hadr; /* high address of packet */
+ short length; /* Length is 2s complement (negative)! */
+ unsigned short misc;
+};
+
+/* The LANCE initialization block, described in databook. */
+/* On the Sparc, this block should be on a DMA region */
+struct lance_init_block {
+ unsigned short mode; /* Pre-set mode (reg. 15) */
+ unsigned char phys_addr[6]; /* Physical ethernet address */
+ unsigned filter[2]; /* Multicast filter. */
+
+ /* Receive and transmit ring base, along with extra bits. */
+ unsigned short rx_ptr; /* receive descriptor addr */
+ unsigned short rx_len; /* receive len and high addr */
+ unsigned short tx_ptr; /* transmit descriptor addr */
+ unsigned short tx_len; /* transmit len and high addr */
+
+ /* The Tx and Rx ring entries must aligned on 8-byte boundaries. */
+ struct lance_rx_desc brx_ring[RX_RING_SIZE];
+ struct lance_tx_desc btx_ring[TX_RING_SIZE];
+
+ char tx_buf [TX_RING_SIZE][TX_BUFF_SIZE];
+ char pad[2]; /* align rx_buf for copy_and_sum(). */
+ char rx_buf [RX_RING_SIZE][RX_BUFF_SIZE];
+};
+
+#define LEDMA_REGS 4
+#if 0
+/* Structure to describe the current status of DMA registers on the Sparc */
+struct sparc_dma_registers {
+ uint32_t cond_reg; /* DMA condition register */
+ uint32_t st_addr; /* Start address of this transfer */
+ uint32_t cnt; /* How many bytes to transfer */
+ uint32_t dma_test; /* DMA test register */
+};
+#endif
+
+typedef struct LEDMAState {
+ uint32_t addr;
+ uint32_t regs[LEDMA_REGS];
+} LEDMAState;
+
+typedef struct LANCEState {
+ uint32_t paddr;
+ NetDriverState *nd;
+ uint32_t leptr;
+ uint16_t addr;
+ uint16_t regs[LE_MAXREG];
+ uint8_t phys[6]; /* mac address */
+ int irq;
+ LEDMAState *ledma;
+} LANCEState;
+
+static unsigned int rxptr, txptr;
+
+static void lance_send(void *opaque);
+
+static void lance_reset(LANCEState *s)
+{
+ memcpy(s->phys, s->nd->macaddr, 6);
+ rxptr = 0;
+ txptr = 0;
+ s->regs[LE_CSR0] = LE_C0_STOP;
+}
+
+static uint32_t lance_mem_readw(void *opaque, target_phys_addr_t addr)
+{
+ LANCEState *s = opaque;
+ uint32_t saddr;
+
+ saddr = addr - s->paddr;
+ switch (saddr >> 1) {
+ case LE_RDP:
+ return s->regs[s->addr];
+ case LE_RAP:
+ return s->addr;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static void lance_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ LANCEState *s = opaque;
+ uint32_t saddr;
+ uint16_t reg;
+
+ saddr = addr - s->paddr;
+ switch (saddr >> 1) {
+ case LE_RDP:
+ switch(s->addr) {
+ case LE_CSR0:
+ if (val & LE_C0_STOP) {
+ s->regs[LE_CSR0] = LE_C0_STOP;
+ break;
+ }
+
+ reg = s->regs[LE_CSR0];
+
+ // 1 = clear for some bits
+ reg &= ~(val & 0x7f00);
+
+ // generated bits
+ reg &= ~(LE_C0_ERR | LE_C0_INTR);
+ if (reg & 0x7100)
+ reg |= LE_C0_ERR;
+ if (reg & 0x7f00)
+ reg |= LE_C0_INTR;
+
+ // direct bit
+ reg &= ~LE_C0_INEA;
+ reg |= val & LE_C0_INEA;
+
+ // exclusive bits
+ if (val & LE_C0_INIT) {
+ reg |= LE_C0_IDON | LE_C0_INIT;
+ reg &= ~LE_C0_STOP;
+ }
+ else if (val & LE_C0_STRT) {
+ reg |= LE_C0_STRT | LE_C0_RXON | LE_C0_TXON;
+ reg &= ~LE_C0_STOP;
+ }
+
+ s->regs[LE_CSR0] = reg;
+
+ // trigger bits
+ //if (val & LE_C0_TDMD)
+
+ if ((s->regs[LE_CSR0] & LE_C0_INTR) && (s->regs[LE_CSR0] & LE_C0_INEA))
+ pic_set_irq(s->irq, 1);
+ break;
+ case LE_CSR1:
+ s->leptr = (s->leptr & 0xffff0000) | (val & 0xffff);
+ s->regs[s->addr] = val;
+ break;
+ case LE_CSR2:
+ s->leptr = (s->leptr & 0xffff) | ((val & 0xffff) << 16);
+ s->regs[s->addr] = val;
+ break;
+ case LE_CSR3:
+ s->regs[s->addr] = val;
+ break;
+ }
+ break;
+ case LE_RAP:
+ if (val < LE_MAXREG)
+ s->addr = val;
+ break;
+ default:
+ break;
+ }
+ lance_send(s);
+}
+
+static CPUReadMemoryFunc *lance_mem_read[3] = {
+ lance_mem_readw,
+ lance_mem_readw,
+ lance_mem_readw,
+};
+
+static CPUWriteMemoryFunc *lance_mem_write[3] = {
+ lance_mem_writew,
+ lance_mem_writew,
+ lance_mem_writew,
+};
+
+
+/* return the max buffer size if the LANCE can receive more data */
+static int lance_can_receive(void *opaque)
+{
+ LANCEState *s = opaque;
+ void *dmaptr = (void *) (s->leptr + s->ledma->regs[3]);
+ struct lance_init_block *ib;
+ int i;
+ uint16_t temp;
+
+ if ((s->regs[LE_CSR0] & LE_C0_STOP) == LE_C0_STOP)
+ return 0;
+
+ ib = (void *) iommu_translate(dmaptr);
+
+ for (i = 0; i < RX_RING_SIZE; i++) {
+ cpu_physical_memory_read(&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1);
+ temp &= 0xff;
+ if (temp == (LE_R1_OWN)) {
+#ifdef DEBUG_LANCE
+ fprintf(stderr, "lance: can receive %d\n", RX_BUFF_SIZE);
+#endif
+ return RX_BUFF_SIZE;
+ }
+ }
+#ifdef DEBUG_LANCE
+ fprintf(stderr, "lance: cannot receive\n");
+#endif
+ return 0;
+}
+
+#define MIN_BUF_SIZE 60
+
+static void lance_receive(void *opaque, const uint8_t *buf, int size)
+{
+ LANCEState *s = opaque;
+ void *dmaptr = (void *) (s->leptr + s->ledma->regs[3]);
+ struct lance_init_block *ib;
+ unsigned int i, old_rxptr, j;
+ uint16_t temp;
+
+ if ((s->regs[LE_CSR0] & LE_C0_STOP) == LE_C0_STOP)
+ return;
+
+ ib = (void *) iommu_translate(dmaptr);
+
+ old_rxptr = rxptr;
+ for (i = rxptr; i != ((old_rxptr - 1) & RX_RING_MOD_MASK); i = (i + 1) & RX_RING_MOD_MASK) {
+ cpu_physical_memory_read(&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1);
+ if (temp == (LE_R1_OWN)) {
+ rxptr = (rxptr + 1) & RX_RING_MOD_MASK;
+ temp = size;
+ bswap16s(&temp);
+ cpu_physical_memory_write(&ib->brx_ring[i].mblength, (void *) &temp, 2);
+#if 0
+ cpu_physical_memory_write(&ib->rx_buf[i], buf, size);
+#else
+ for (j = 0; j < size; j++) {
+ cpu_physical_memory_write(((void *)&ib->rx_buf[i]) + j, &buf[j], 1);
+ }
+#endif
+ temp = LE_R1_POK;
+ cpu_physical_memory_write(&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1);
+ s->regs[LE_CSR0] |= LE_C0_RINT | LE_C0_INTR;
+ if ((s->regs[LE_CSR0] & LE_C0_INTR) && (s->regs[LE_CSR0] & LE_C0_INEA))
+ pic_set_irq(s->irq, 1);
+#ifdef DEBUG_LANCE
+ fprintf(stderr, "lance: got packet, len %d\n", size);
+#endif
+ return;
+ }
+ }
+}
+
+static void lance_send(void *opaque)
+{
+ LANCEState *s = opaque;
+ void *dmaptr = (void *) (s->leptr + s->ledma->regs[3]);
+ struct lance_init_block *ib;
+ unsigned int i, old_txptr, j;
+ uint16_t temp;
+ char pkt_buf[PKT_BUF_SZ];
+
+ if ((s->regs[LE_CSR0] & LE_C0_STOP) == LE_C0_STOP)
+ return;
+
+ ib = (void *) iommu_translate(dmaptr);
+
+ old_txptr = txptr;
+ for (i = txptr; i != ((old_txptr - 1) & TX_RING_MOD_MASK); i = (i + 1) & TX_RING_MOD_MASK) {
+ cpu_physical_memory_read(&ib->btx_ring[i].tmd1_bits, (void *) &temp, 1);
+ if (temp == (LE_T1_POK|LE_T1_OWN)) {
+ cpu_physical_memory_read(&ib->btx_ring[i].length, (void *) &temp, 2);
+ bswap16s(&temp);
+ temp = (~temp) + 1;
+#if 0
+ cpu_physical_memory_read(&ib->tx_buf[i], pkt_buf, temp);
+#else
+ for (j = 0; j < temp; j++) {
+ cpu_physical_memory_read(((void *)&ib->tx_buf[i]) + j, &pkt_buf[j], 1);
+ }
+#endif
+
+#ifdef DEBUG_LANCE
+ fprintf(stderr, "lance: sending packet, len %d\n", temp);
+#endif
+ qemu_send_packet(s->nd, pkt_buf, temp);
+ temp = LE_T1_POK;
+ cpu_physical_memory_write(&ib->btx_ring[i].tmd1_bits, (void *) &temp, 1);
+ txptr = (txptr + 1) & TX_RING_MOD_MASK;
+ s->regs[LE_CSR0] |= LE_C0_TINT | LE_C0_INTR;
+ }
+ }
+}
+
+static uint32_t ledma_mem_readl(void *opaque, target_phys_addr_t addr)
+{
+ LEDMAState *s = opaque;
+ uint32_t saddr;
+
+ saddr = (addr - s->addr) >> 2;
+ if (saddr < LEDMA_REGS)
+ return s->regs[saddr];
+ else
+ return 0;
+}
+
+static void ledma_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ LEDMAState *s = opaque;
+ uint32_t saddr;
+
+ saddr = (addr - s->addr) >> 2;
+ if (saddr < LEDMA_REGS)
+ s->regs[saddr] = val;
+}
+
+static CPUReadMemoryFunc *ledma_mem_read[3] = {
+ ledma_mem_readl,
+ ledma_mem_readl,
+ ledma_mem_readl,
+};
+
+static CPUWriteMemoryFunc *ledma_mem_write[3] = {
+ ledma_mem_writel,
+ ledma_mem_writel,
+ ledma_mem_writel,
+};
+
+void lance_init(NetDriverState *nd, int irq, uint32_t leaddr, uint32_t ledaddr)
+{
+ LANCEState *s;
+ LEDMAState *led;
+ int lance_io_memory, ledma_io_memory;
+
+ s = qemu_mallocz(sizeof(LANCEState));
+ if (!s)
+ return;
+
+ s->paddr = leaddr;
+ s->nd = nd;
+ s->irq = irq;
+
+ lance_io_memory = cpu_register_io_memory(0, lance_mem_read, lance_mem_write, s);
+ cpu_register_physical_memory(leaddr, 8, lance_io_memory);
+
+ led = qemu_mallocz(sizeof(LEDMAState));
+ if (!led)
+ return;
+
+ s->ledma = led;
+ led->addr = ledaddr;
+ ledma_io_memory = cpu_register_io_memory(0, ledma_mem_read, ledma_mem_write, led);
+ cpu_register_physical_memory(ledaddr, 16, ledma_io_memory);
+
+ lance_reset(s);
+ qemu_add_read_packet(nd, lance_can_receive, lance_receive, s);
+}
+
--- /dev/null
+/*
+ * QEMU M48T08 NVRAM emulation for Sparc platform
+ *
+ * Copyright (c) 2003-2004 Jocelyn Mayer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+#include "m48t08.h"
+
+//#define DEBUG_NVRAM
+
+#if defined(DEBUG_NVRAM)
+#define NVRAM_PRINTF(fmt, args...) do { printf(fmt , ##args); } while (0)
+#else
+#define NVRAM_PRINTF(fmt, args...) do { } while (0)
+#endif
+
+#define NVRAM_MAX_MEM 0xfff0
+
+struct m48t08_t {
+ /* Hardware parameters */
+ int mem_index;
+ uint32_t mem_base;
+ uint16_t size;
+ /* RTC management */
+ time_t time_offset;
+ time_t stop_time;
+ /* NVRAM storage */
+ uint8_t lock;
+ uint16_t addr;
+ uint8_t *buffer;
+};
+
+/* Fake timer functions */
+/* Generic helpers for BCD */
+static inline uint8_t toBCD (uint8_t value)
+{
+ return (((value / 10) % 10) << 4) | (value % 10);
+}
+
+static inline uint8_t fromBCD (uint8_t BCD)
+{
+ return ((BCD >> 4) * 10) + (BCD & 0x0F);
+}
+
+/* RTC management helpers */
+static void get_time (m48t08_t *NVRAM, struct tm *tm)
+{
+ time_t t;
+
+ t = time(NULL) + NVRAM->time_offset;
+#ifdef _WIN32
+ memcpy(tm,localtime(&t),sizeof(*tm));
+#else
+ localtime_r (&t, tm) ;
+#endif
+}
+
+static void set_time (m48t08_t *NVRAM, struct tm *tm)
+{
+ time_t now, new_time;
+
+ new_time = mktime(tm);
+ now = time(NULL);
+ NVRAM->time_offset = new_time - now;
+}
+
+/* Direct access to NVRAM */
+void m48t08_write (m48t08_t *NVRAM, uint32_t val)
+{
+ struct tm tm;
+ int tmp;
+
+ if (NVRAM->addr > NVRAM_MAX_MEM && NVRAM->addr < 0x2000)
+ NVRAM_PRINTF("%s: 0x%08x => 0x%08x\n", __func__, NVRAM->addr, val);
+ switch (NVRAM->addr) {
+ case 0x1FF8:
+ /* control */
+ NVRAM->buffer[0x1FF8] = (val & ~0xA0) | 0x90;
+ break;
+ case 0x1FF9:
+ /* seconds (BCD) */
+ tmp = fromBCD(val & 0x7F);
+ if (tmp >= 0 && tmp <= 59) {
+ get_time(NVRAM, &tm);
+ tm.tm_sec = tmp;
+ set_time(NVRAM, &tm);
+ }
+ if ((val & 0x80) ^ (NVRAM->buffer[0x1FF9] & 0x80)) {
+ if (val & 0x80) {
+ NVRAM->stop_time = time(NULL);
+ } else {
+ NVRAM->time_offset += NVRAM->stop_time - time(NULL);
+ NVRAM->stop_time = 0;
+ }
+ }
+ NVRAM->buffer[0x1FF9] = val & 0x80;
+ break;
+ case 0x1FFA:
+ /* minutes (BCD) */
+ tmp = fromBCD(val & 0x7F);
+ if (tmp >= 0 && tmp <= 59) {
+ get_time(NVRAM, &tm);
+ tm.tm_min = tmp;
+ set_time(NVRAM, &tm);
+ }
+ break;
+ case 0x1FFB:
+ /* hours (BCD) */
+ tmp = fromBCD(val & 0x3F);
+ if (tmp >= 0 && tmp <= 23) {
+ get_time(NVRAM, &tm);
+ tm.tm_hour = tmp;
+ set_time(NVRAM, &tm);
+ }
+ break;
+ case 0x1FFC:
+ /* day of the week / century */
+ tmp = fromBCD(val & 0x07);
+ get_time(NVRAM, &tm);
+ tm.tm_wday = tmp;
+ set_time(NVRAM, &tm);
+ NVRAM->buffer[0x1FFC] = val & 0x40;
+ break;
+ case 0x1FFD:
+ /* date */
+ tmp = fromBCD(val & 0x1F);
+ if (tmp != 0) {
+ get_time(NVRAM, &tm);
+ tm.tm_mday = tmp;
+ set_time(NVRAM, &tm);
+ }
+ break;
+ case 0x1FFE:
+ /* month */
+ tmp = fromBCD(val & 0x1F);
+ if (tmp >= 1 && tmp <= 12) {
+ get_time(NVRAM, &tm);
+ tm.tm_mon = tmp - 1;
+ set_time(NVRAM, &tm);
+ }
+ break;
+ case 0x1FFF:
+ /* year */
+ tmp = fromBCD(val);
+ if (tmp >= 0 && tmp <= 99) {
+ get_time(NVRAM, &tm);
+ tm.tm_year = fromBCD(val);
+ set_time(NVRAM, &tm);
+ }
+ break;
+ default:
+ /* Check lock registers state */
+ if (NVRAM->addr >= 0x20 && NVRAM->addr <= 0x2F && (NVRAM->lock & 1))
+ break;
+ if (NVRAM->addr >= 0x30 && NVRAM->addr <= 0x3F && (NVRAM->lock & 2))
+ break;
+ if (NVRAM->addr < NVRAM_MAX_MEM ||
+ (NVRAM->addr > 0x1FFF && NVRAM->addr < NVRAM->size)) {
+ NVRAM->buffer[NVRAM->addr] = val & 0xFF;
+ }
+ break;
+ }
+}
+
+uint32_t m48t08_read (m48t08_t *NVRAM)
+{
+ struct tm tm;
+ uint32_t retval = 0xFF;
+
+ switch (NVRAM->addr) {
+ case 0x1FF8:
+ /* control */
+ goto do_read;
+ case 0x1FF9:
+ /* seconds (BCD) */
+ get_time(NVRAM, &tm);
+ retval = (NVRAM->buffer[0x1FF9] & 0x80) | toBCD(tm.tm_sec);
+ break;
+ case 0x1FFA:
+ /* minutes (BCD) */
+ get_time(NVRAM, &tm);
+ retval = toBCD(tm.tm_min);
+ break;
+ case 0x1FFB:
+ /* hours (BCD) */
+ get_time(NVRAM, &tm);
+ retval = toBCD(tm.tm_hour);
+ break;
+ case 0x1FFC:
+ /* day of the week / century */
+ get_time(NVRAM, &tm);
+ retval = NVRAM->buffer[0x1FFC] | tm.tm_wday;
+ break;
+ case 0x1FFD:
+ /* date */
+ get_time(NVRAM, &tm);
+ retval = toBCD(tm.tm_mday);
+ break;
+ case 0x1FFE:
+ /* month */
+ get_time(NVRAM, &tm);
+ retval = toBCD(tm.tm_mon + 1);
+ break;
+ case 0x1FFF:
+ /* year */
+ get_time(NVRAM, &tm);
+ retval = toBCD(tm.tm_year);
+ break;
+ default:
+ /* Check lock registers state */
+ if (NVRAM->addr >= 0x20 && NVRAM->addr <= 0x2F && (NVRAM->lock & 1))
+ break;
+ if (NVRAM->addr >= 0x30 && NVRAM->addr <= 0x3F && (NVRAM->lock & 2))
+ break;
+ if (NVRAM->addr < NVRAM_MAX_MEM ||
+ (NVRAM->addr > 0x1FFF && NVRAM->addr < NVRAM->size)) {
+ do_read:
+ retval = NVRAM->buffer[NVRAM->addr];
+ }
+ break;
+ }
+ if (NVRAM->addr > NVRAM_MAX_MEM + 1 && NVRAM->addr < 0x2000)
+ NVRAM_PRINTF("0x%08x <= 0x%08x\n", NVRAM->addr, retval);
+
+ return retval;
+}
+
+void m48t08_set_addr (m48t08_t *NVRAM, uint32_t addr)
+{
+ NVRAM->addr = addr;
+}
+
+void m48t08_toggle_lock (m48t08_t *NVRAM, int lock)
+{
+ NVRAM->lock ^= 1 << lock;
+}
+
+static void nvram_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+ m48t08_t *NVRAM = opaque;
+
+ addr -= NVRAM->mem_base;
+ if (addr < NVRAM_MAX_MEM)
+ NVRAM->buffer[addr] = value;
+}
+
+static void nvram_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+ m48t08_t *NVRAM = opaque;
+
+ addr -= NVRAM->mem_base;
+ if (addr < NVRAM_MAX_MEM) {
+ NVRAM->buffer[addr] = value >> 8;
+ NVRAM->buffer[addr + 1] = value;
+ }
+}
+
+static void nvram_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+ m48t08_t *NVRAM = opaque;
+
+ addr -= NVRAM->mem_base;
+ if (addr < NVRAM_MAX_MEM) {
+ NVRAM->buffer[addr] = value >> 24;
+ NVRAM->buffer[addr + 1] = value >> 16;
+ NVRAM->buffer[addr + 2] = value >> 8;
+ NVRAM->buffer[addr + 3] = value;
+ }
+}
+
+static uint32_t nvram_readb (void *opaque, target_phys_addr_t addr)
+{
+ m48t08_t *NVRAM = opaque;
+ uint32_t retval = 0;
+
+ addr -= NVRAM->mem_base;
+ if (addr < NVRAM_MAX_MEM)
+ retval = NVRAM->buffer[addr];
+
+ return retval;
+}
+
+static uint32_t nvram_readw (void *opaque, target_phys_addr_t addr)
+{
+ m48t08_t *NVRAM = opaque;
+ uint32_t retval = 0;
+
+ addr -= NVRAM->mem_base;
+ if (addr < NVRAM_MAX_MEM) {
+ retval = NVRAM->buffer[addr] << 8;
+ retval |= NVRAM->buffer[addr + 1];
+ }
+
+ return retval;
+}
+
+static uint32_t nvram_readl (void *opaque, target_phys_addr_t addr)
+{
+ m48t08_t *NVRAM = opaque;
+ uint32_t retval = 0;
+
+ addr -= NVRAM->mem_base;
+ if (addr < NVRAM_MAX_MEM) {
+ retval = NVRAM->buffer[addr] << 24;
+ retval |= NVRAM->buffer[addr + 1] << 16;
+ retval |= NVRAM->buffer[addr + 2] << 8;
+ retval |= NVRAM->buffer[addr + 3];
+ }
+
+ return retval;
+}
+
+static CPUWriteMemoryFunc *nvram_write[] = {
+ &nvram_writeb,
+ &nvram_writew,
+ &nvram_writel,
+};
+
+static CPUReadMemoryFunc *nvram_read[] = {
+ &nvram_readb,
+ &nvram_readw,
+ &nvram_readl,
+};
+
+/* Initialisation routine */
+m48t08_t *m48t08_init(uint32_t mem_base, uint16_t size, uint8_t *macaddr)
+{
+ m48t08_t *s;
+ int i;
+ unsigned char tmp = 0;
+
+ s = qemu_mallocz(sizeof(m48t08_t));
+ if (!s)
+ return NULL;
+ s->buffer = qemu_mallocz(size);
+ if (!s->buffer) {
+ qemu_free(s);
+ return NULL;
+ }
+ s->size = size;
+ s->mem_base = mem_base;
+ s->addr = 0;
+ if (mem_base != 0) {
+ s->mem_index = cpu_register_io_memory(0, nvram_read, nvram_write, s);
+ cpu_register_physical_memory(mem_base, 0x4000, s->mem_index);
+ }
+ s->lock = 0;
+
+ i = 0x1fd8;
+ s->buffer[i++] = 0x01;
+ s->buffer[i++] = 0x80; /* Sun4m OBP */
+ memcpy(&s->buffer[i], macaddr, 6);
+
+ /* Calculate checksum */
+ for (i = 0x1fd8; i < 0x1fe7; i++) {
+ tmp ^= s->buffer[i];
+ }
+ s->buffer[0x1fe7] = tmp;
+ return s;
+}
+
+#if 0
+struct idprom
+{
+ unsigned char id_format; /* Format identifier (always 0x01) */
+ unsigned char id_machtype; /* Machine type */
+ unsigned char id_ethaddr[6]; /* Hardware ethernet address */
+ long id_date; /* Date of manufacture */
+ unsigned int id_sernum:24; /* Unique serial number */
+ unsigned char id_cksum; /* Checksum - xor of the data bytes */
+ unsigned char reserved[16];
+};
+#endif
--- /dev/null
+#if !defined (__M48T08_H__)
+#define __M48T08_H__
+
+typedef struct m48t08_t m48t08_t;
+
+void m48t08_write (m48t08_t *NVRAM, uint32_t val);
+uint32_t m48t08_read (m48t08_t *NVRAM);
+void m48t08_set_addr (m48t08_t *NVRAM, uint32_t addr);
+void m48t08_toggle_lock (m48t08_t *NVRAM, int lock);
+m48t08_t *m48t08_init(uint32_t mem_base, uint16_t size, uint8_t *macaddr);
+
+#endif /* !defined (__M48T08_H__) */
--- /dev/null
+/*
+ * QEMU M48T59 NVRAM emulation for PPC PREP platform
+ *
+ * Copyright (c) 2003-2004 Jocelyn Mayer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+#include "m48t59.h"
+
+//#define DEBUG_NVRAM
+
+#if defined(DEBUG_NVRAM)
+#define NVRAM_PRINTF(fmt, args...) do { printf(fmt , ##args); } while (0)
+#else
+#define NVRAM_PRINTF(fmt, args...) do { } while (0)
+#endif
+
+struct m48t59_t {
+ /* Hardware parameters */
+ int IRQ;
+ int mem_index;
+ uint32_t mem_base;
+ uint32_t io_base;
+ uint16_t size;
+ /* RTC management */
+ time_t time_offset;
+ time_t stop_time;
+ /* Alarm & watchdog */
+ time_t alarm;
+ struct QEMUTimer *alrm_timer;
+ struct QEMUTimer *wd_timer;
+ /* NVRAM storage */
+ uint8_t lock;
+ uint16_t addr;
+ uint8_t *buffer;
+};
+
+/* Fake timer functions */
+/* Generic helpers for BCD */
+static inline uint8_t toBCD (uint8_t value)
+{
+ return (((value / 10) % 10) << 4) | (value % 10);
+}
+
+static inline uint8_t fromBCD (uint8_t BCD)
+{
+ return ((BCD >> 4) * 10) + (BCD & 0x0F);
+}
+
+/* RTC management helpers */
+static void get_time (m48t59_t *NVRAM, struct tm *tm)
+{
+ time_t t;
+
+ t = time(NULL) + NVRAM->time_offset;
+#ifdef _WIN32
+ memcpy(tm,localtime(&t),sizeof(*tm));
+#else
+ localtime_r (&t, tm) ;
+#endif
+}
+
+static void set_time (m48t59_t *NVRAM, struct tm *tm)
+{
+ time_t now, new_time;
+
+ new_time = mktime(tm);
+ now = time(NULL);
+ NVRAM->time_offset = new_time - now;
+}
+
+/* Alarm management */
+static void alarm_cb (void *opaque)
+{
+ struct tm tm, tm_now;
+ uint64_t next_time;
+ m48t59_t *NVRAM = opaque;
+
+ pic_set_irq(NVRAM->IRQ, 1);
+ if ((NVRAM->buffer[0x1FF5] & 0x80) == 0 &&
+ (NVRAM->buffer[0x1FF4] & 0x80) == 0 &&
+ (NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
+ (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
+ /* Repeat once a month */
+ get_time(NVRAM, &tm_now);
+ memcpy(&tm, &tm_now, sizeof(struct tm));
+ tm.tm_mon++;
+ if (tm.tm_mon == 13) {
+ tm.tm_mon = 1;
+ tm.tm_year++;
+ }
+ next_time = mktime(&tm);
+ } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
+ (NVRAM->buffer[0x1FF4] & 0x80) == 0 &&
+ (NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
+ (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
+ /* Repeat once a day */
+ next_time = 24 * 60 * 60 + mktime(&tm_now);
+ } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
+ (NVRAM->buffer[0x1FF4] & 0x80) != 0 &&
+ (NVRAM->buffer[0x1FF3] & 0x80) == 0 &&
+ (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
+ /* Repeat once an hour */
+ next_time = 60 * 60 + mktime(&tm_now);
+ } else if ((NVRAM->buffer[0x1FF5] & 0x80) != 0 &&
+ (NVRAM->buffer[0x1FF4] & 0x80) != 0 &&
+ (NVRAM->buffer[0x1FF3] & 0x80) != 0 &&
+ (NVRAM->buffer[0x1FF2] & 0x80) == 0) {
+ /* Repeat once a minute */
+ next_time = 60 + mktime(&tm_now);
+ } else {
+ /* Repeat once a second */
+ next_time = 1 + mktime(&tm_now);
+ }
+ qemu_mod_timer(NVRAM->alrm_timer, next_time * 1000);
+ pic_set_irq(NVRAM->IRQ, 0);
+}
+
+
+static void get_alarm (m48t59_t *NVRAM, struct tm *tm)
+{
+#ifdef _WIN32
+ memcpy(tm,localtime(&NVRAM->alarm),sizeof(*tm));
+#else
+ localtime_r (&NVRAM->alarm, tm);
+#endif
+}
+
+static void set_alarm (m48t59_t *NVRAM, struct tm *tm)
+{
+ NVRAM->alarm = mktime(tm);
+ if (NVRAM->alrm_timer != NULL) {
+ qemu_del_timer(NVRAM->alrm_timer);
+ NVRAM->alrm_timer = NULL;
+ }
+ if (NVRAM->alarm - time(NULL) > 0)
+ qemu_mod_timer(NVRAM->alrm_timer, NVRAM->alarm * 1000);
+}
+
+/* Watchdog management */
+static void watchdog_cb (void *opaque)
+{
+ m48t59_t *NVRAM = opaque;
+
+ NVRAM->buffer[0x1FF0] |= 0x80;
+ if (NVRAM->buffer[0x1FF7] & 0x80) {
+ NVRAM->buffer[0x1FF7] = 0x00;
+ NVRAM->buffer[0x1FFC] &= ~0x40;
+ /* May it be a hw CPU Reset instead ? */
+ qemu_system_reset_request();
+ } else {
+ pic_set_irq(NVRAM->IRQ, 1);
+ pic_set_irq(NVRAM->IRQ, 0);
+ }
+}
+
+static void set_up_watchdog (m48t59_t *NVRAM, uint8_t value)
+{
+ uint64_t interval; /* in 1/16 seconds */
+
+ if (NVRAM->wd_timer != NULL) {
+ qemu_del_timer(NVRAM->wd_timer);
+ NVRAM->wd_timer = NULL;
+ }
+ NVRAM->buffer[0x1FF0] &= ~0x80;
+ if (value != 0) {
+ interval = (1 << (2 * (value & 0x03))) * ((value >> 2) & 0x1F);
+ qemu_mod_timer(NVRAM->wd_timer, ((uint64_t)time(NULL) * 1000) +
+ ((interval * 1000) >> 4));
+ }
+}
+
+/* Direct access to NVRAM */
+void m48t59_write (m48t59_t *NVRAM, uint32_t val)
+{
+ struct tm tm;
+ int tmp;
+
+ if (NVRAM->addr > 0x1FF8 && NVRAM->addr < 0x2000)
+ NVRAM_PRINTF("%s: 0x%08x => 0x%08x\n", __func__, NVRAM->addr, val);
+ switch (NVRAM->addr) {
+ case 0x1FF0:
+ /* flags register : read-only */
+ break;
+ case 0x1FF1:
+ /* unused */
+ break;
+ case 0x1FF2:
+ /* alarm seconds */
+ tmp = fromBCD(val & 0x7F);
+ if (tmp >= 0 && tmp <= 59) {
+ get_alarm(NVRAM, &tm);
+ tm.tm_sec = tmp;
+ NVRAM->buffer[0x1FF2] = val;
+ set_alarm(NVRAM, &tm);
+ }
+ break;
+ case 0x1FF3:
+ /* alarm minutes */
+ tmp = fromBCD(val & 0x7F);
+ if (tmp >= 0 && tmp <= 59) {
+ get_alarm(NVRAM, &tm);
+ tm.tm_min = tmp;
+ NVRAM->buffer[0x1FF3] = val;
+ set_alarm(NVRAM, &tm);
+ }
+ break;
+ case 0x1FF4:
+ /* alarm hours */
+ tmp = fromBCD(val & 0x3F);
+ if (tmp >= 0 && tmp <= 23) {
+ get_alarm(NVRAM, &tm);
+ tm.tm_hour = tmp;
+ NVRAM->buffer[0x1FF4] = val;
+ set_alarm(NVRAM, &tm);
+ }
+ break;
+ case 0x1FF5:
+ /* alarm date */
+ tmp = fromBCD(val & 0x1F);
+ if (tmp != 0) {
+ get_alarm(NVRAM, &tm);
+ tm.tm_mday = tmp;
+ NVRAM->buffer[0x1FF5] = val;
+ set_alarm(NVRAM, &tm);
+ }
+ break;
+ case 0x1FF6:
+ /* interrupts */
+ NVRAM->buffer[0x1FF6] = val;
+ break;
+ case 0x1FF7:
+ /* watchdog */
+ NVRAM->buffer[0x1FF7] = val;
+ set_up_watchdog(NVRAM, val);
+ break;
+ case 0x1FF8:
+ /* control */
+ NVRAM->buffer[0x1FF8] = (val & ~0xA0) | 0x90;
+ break;
+ case 0x1FF9:
+ /* seconds (BCD) */
+ tmp = fromBCD(val & 0x7F);
+ if (tmp >= 0 && tmp <= 59) {
+ get_time(NVRAM, &tm);
+ tm.tm_sec = tmp;
+ set_time(NVRAM, &tm);
+ }
+ if ((val & 0x80) ^ (NVRAM->buffer[0x1FF9] & 0x80)) {
+ if (val & 0x80) {
+ NVRAM->stop_time = time(NULL);
+ } else {
+ NVRAM->time_offset += NVRAM->stop_time - time(NULL);
+ NVRAM->stop_time = 0;
+ }
+ }
+ NVRAM->buffer[0x1FF9] = val & 0x80;
+ break;
+ case 0x1FFA:
+ /* minutes (BCD) */
+ tmp = fromBCD(val & 0x7F);
+ if (tmp >= 0 && tmp <= 59) {
+ get_time(NVRAM, &tm);
+ tm.tm_min = tmp;
+ set_time(NVRAM, &tm);
+ }
+ break;
+ case 0x1FFB:
+ /* hours (BCD) */
+ tmp = fromBCD(val & 0x3F);
+ if (tmp >= 0 && tmp <= 23) {
+ get_time(NVRAM, &tm);
+ tm.tm_hour = tmp;
+ set_time(NVRAM, &tm);
+ }
+ break;
+ case 0x1FFC:
+ /* day of the week / century */
+ tmp = fromBCD(val & 0x07);
+ get_time(NVRAM, &tm);
+ tm.tm_wday = tmp;
+ set_time(NVRAM, &tm);
+ NVRAM->buffer[0x1FFC] = val & 0x40;
+ break;
+ case 0x1FFD:
+ /* date */
+ tmp = fromBCD(val & 0x1F);
+ if (tmp != 0) {
+ get_time(NVRAM, &tm);
+ tm.tm_mday = tmp;
+ set_time(NVRAM, &tm);
+ }
+ break;
+ case 0x1FFE:
+ /* month */
+ tmp = fromBCD(val & 0x1F);
+ if (tmp >= 1 && tmp <= 12) {
+ get_time(NVRAM, &tm);
+ tm.tm_mon = tmp - 1;
+ set_time(NVRAM, &tm);
+ }
+ break;
+ case 0x1FFF:
+ /* year */
+ tmp = fromBCD(val);
+ if (tmp >= 0 && tmp <= 99) {
+ get_time(NVRAM, &tm);
+ tm.tm_year = fromBCD(val);
+ set_time(NVRAM, &tm);
+ }
+ break;
+ default:
+ /* Check lock registers state */
+ if (NVRAM->addr >= 0x20 && NVRAM->addr <= 0x2F && (NVRAM->lock & 1))
+ break;
+ if (NVRAM->addr >= 0x30 && NVRAM->addr <= 0x3F && (NVRAM->lock & 2))
+ break;
+ if (NVRAM->addr < 0x1FF0 ||
+ (NVRAM->addr > 0x1FFF && NVRAM->addr < NVRAM->size)) {
+ NVRAM->buffer[NVRAM->addr] = val & 0xFF;
+ }
+ break;
+ }
+}
+
+uint32_t m48t59_read (m48t59_t *NVRAM)
+{
+ struct tm tm;
+ uint32_t retval = 0xFF;
+
+ switch (NVRAM->addr) {
+ case 0x1FF0:
+ /* flags register */
+ goto do_read;
+ case 0x1FF1:
+ /* unused */
+ retval = 0;
+ break;
+ case 0x1FF2:
+ /* alarm seconds */
+ goto do_read;
+ case 0x1FF3:
+ /* alarm minutes */
+ goto do_read;
+ case 0x1FF4:
+ /* alarm hours */
+ goto do_read;
+ case 0x1FF5:
+ /* alarm date */
+ goto do_read;
+ case 0x1FF6:
+ /* interrupts */
+ goto do_read;
+ case 0x1FF7:
+ /* A read resets the watchdog */
+ set_up_watchdog(NVRAM, NVRAM->buffer[0x1FF7]);
+ goto do_read;
+ case 0x1FF8:
+ /* control */
+ goto do_read;
+ case 0x1FF9:
+ /* seconds (BCD) */
+ get_time(NVRAM, &tm);
+ retval = (NVRAM->buffer[0x1FF9] & 0x80) | toBCD(tm.tm_sec);
+ break;
+ case 0x1FFA:
+ /* minutes (BCD) */
+ get_time(NVRAM, &tm);
+ retval = toBCD(tm.tm_min);
+ break;
+ case 0x1FFB:
+ /* hours (BCD) */
+ get_time(NVRAM, &tm);
+ retval = toBCD(tm.tm_hour);
+ break;
+ case 0x1FFC:
+ /* day of the week / century */
+ get_time(NVRAM, &tm);
+ retval = NVRAM->buffer[0x1FFC] | tm.tm_wday;
+ break;
+ case 0x1FFD:
+ /* date */
+ get_time(NVRAM, &tm);
+ retval = toBCD(tm.tm_mday);
+ break;
+ case 0x1FFE:
+ /* month */
+ get_time(NVRAM, &tm);
+ retval = toBCD(tm.tm_mon + 1);
+ break;
+ case 0x1FFF:
+ /* year */
+ get_time(NVRAM, &tm);
+ retval = toBCD(tm.tm_year);
+ break;
+ default:
+ /* Check lock registers state */
+ if (NVRAM->addr >= 0x20 && NVRAM->addr <= 0x2F && (NVRAM->lock & 1))
+ break;
+ if (NVRAM->addr >= 0x30 && NVRAM->addr <= 0x3F && (NVRAM->lock & 2))
+ break;
+ if (NVRAM->addr < 0x1FF0 ||
+ (NVRAM->addr > 0x1FFF && NVRAM->addr < NVRAM->size)) {
+ do_read:
+ retval = NVRAM->buffer[NVRAM->addr];
+ }
+ break;
+ }
+ if (NVRAM->addr > 0x1FF9 && NVRAM->addr < 0x2000)
+ NVRAM_PRINTF("0x%08x <= 0x%08x\n", NVRAM->addr, retval);
+
+ return retval;
+}
+
+void m48t59_set_addr (m48t59_t *NVRAM, uint32_t addr)
+{
+ NVRAM->addr = addr;
+}
+
+void m48t59_toggle_lock (m48t59_t *NVRAM, int lock)
+{
+ NVRAM->lock ^= 1 << lock;
+}
+
+/* IO access to NVRAM */
+static void NVRAM_writeb (void *opaque, uint32_t addr, uint32_t val)
+{
+ m48t59_t *NVRAM = opaque;
+
+ addr -= NVRAM->io_base;
+ NVRAM_PRINTF("0x%08x => 0x%08x\n", addr, val);
+ switch (addr) {
+ case 0:
+ NVRAM->addr &= ~0x00FF;
+ NVRAM->addr |= val;
+ break;
+ case 1:
+ NVRAM->addr &= ~0xFF00;
+ NVRAM->addr |= val << 8;
+ break;
+ case 3:
+ m48t59_write(NVRAM, val);
+ NVRAM->addr = 0x0000;
+ break;
+ default:
+ break;
+ }
+}
+
+static uint32_t NVRAM_readb (void *opaque, uint32_t addr)
+{
+ m48t59_t *NVRAM = opaque;
+ uint32_t retval;
+
+ addr -= NVRAM->io_base;
+ switch (addr) {
+ case 3:
+ retval = m48t59_read(NVRAM);
+ break;
+ default:
+ retval = -1;
+ break;
+ }
+ NVRAM_PRINTF("0x%08x <= 0x%08x\n", addr, retval);
+
+ return retval;
+}
+
+static void nvram_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+ m48t59_t *NVRAM = opaque;
+
+ addr -= NVRAM->mem_base;
+ if (addr < 0x1FF0)
+ NVRAM->buffer[addr] = value;
+}
+
+static void nvram_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+ m48t59_t *NVRAM = opaque;
+
+ addr -= NVRAM->mem_base;
+ if (addr < 0x1FF0) {
+ NVRAM->buffer[addr] = value >> 8;
+ NVRAM->buffer[addr + 1] = value;
+ }
+}
+
+static void nvram_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+ m48t59_t *NVRAM = opaque;
+
+ addr -= NVRAM->mem_base;
+ if (addr < 0x1FF0) {
+ NVRAM->buffer[addr] = value >> 24;
+ NVRAM->buffer[addr + 1] = value >> 16;
+ NVRAM->buffer[addr + 2] = value >> 8;
+ NVRAM->buffer[addr + 3] = value;
+ }
+}
+
+static uint32_t nvram_readb (void *opaque, target_phys_addr_t addr)
+{
+ m48t59_t *NVRAM = opaque;
+ uint32_t retval = 0;
+
+ addr -= NVRAM->mem_base;
+ if (addr < 0x1FF0)
+ retval = NVRAM->buffer[addr];
+
+ return retval;
+}
+
+static uint32_t nvram_readw (void *opaque, target_phys_addr_t addr)
+{
+ m48t59_t *NVRAM = opaque;
+ uint32_t retval = 0;
+
+ addr -= NVRAM->mem_base;
+ if (addr < 0x1FF0) {
+ retval = NVRAM->buffer[addr] << 8;
+ retval |= NVRAM->buffer[addr + 1];
+ }
+
+ return retval;
+}
+
+static uint32_t nvram_readl (void *opaque, target_phys_addr_t addr)
+{
+ m48t59_t *NVRAM = opaque;
+ uint32_t retval = 0;
+
+ addr -= NVRAM->mem_base;
+ if (addr < 0x1FF0) {
+ retval = NVRAM->buffer[addr] << 24;
+ retval |= NVRAM->buffer[addr + 1] << 16;
+ retval |= NVRAM->buffer[addr + 2] << 8;
+ retval |= NVRAM->buffer[addr + 3];
+ }
+
+ return retval;
+}
+
+static CPUWriteMemoryFunc *nvram_write[] = {
+ &nvram_writeb,
+ &nvram_writew,
+ &nvram_writel,
+};
+
+static CPUReadMemoryFunc *nvram_read[] = {
+ &nvram_readb,
+ &nvram_readw,
+ &nvram_readl,
+};
+/* Initialisation routine */
+m48t59_t *m48t59_init (int IRQ, uint32_t mem_base,
+ uint32_t io_base, uint16_t size)
+{
+ m48t59_t *s;
+
+ s = qemu_mallocz(sizeof(m48t59_t));
+ if (!s)
+ return NULL;
+ s->buffer = qemu_mallocz(size);
+ if (!s->buffer) {
+ qemu_free(s);
+ return NULL;
+ }
+ s->IRQ = IRQ;
+ s->size = size;
+ s->mem_base = mem_base;
+ s->io_base = io_base;
+ s->addr = 0;
+ register_ioport_read(io_base, 0x04, 1, NVRAM_readb, s);
+ register_ioport_write(io_base, 0x04, 1, NVRAM_writeb, s);
+ if (mem_base != 0) {
+ s->mem_index = cpu_register_io_memory(0, nvram_read, nvram_write, s);
+ cpu_register_physical_memory(mem_base, 0x4000, s->mem_index);
+ }
+ s->alrm_timer = qemu_new_timer(vm_clock, &alarm_cb, s);
+ s->wd_timer = qemu_new_timer(vm_clock, &watchdog_cb, s);
+ s->lock = 0;
+
+ return s;
+}
--- /dev/null
+#if !defined (__M48T59_H__)
+#define __M48T59_H__
+
+typedef struct m48t59_t m48t59_t;
+
+void m48t59_write (m48t59_t *NVRAM, uint32_t val);
+uint32_t m48t59_read (m48t59_t *NVRAM);
+void m48t59_set_addr (m48t59_t *NVRAM, uint32_t addr);
+void m48t59_toggle_lock (m48t59_t *NVRAM, int lock);
+m48t59_t *m48t59_init (int IRQ, uint32_t io_base,
+ uint32_t mem_base, uint16_t size);
+
+#endif /* !defined (__M48T59_H__) */
--- /dev/null
+#include "vl.h"
+#include "disas.h"
+
+#define ELF_CLASS ELFCLASS32
+#define ELF_DATA ELFDATA2MSB
+#define ELF_ARCH EM_SPARC
+
+#include "elf.h"
+
+#ifdef BSWAP_NEEDED
+static void bswap_ehdr(Elf32_Ehdr *ehdr)
+{
+ bswap16s(&ehdr->e_type); /* Object file type */
+ bswap16s(&ehdr->e_machine); /* Architecture */
+ bswap32s(&ehdr->e_version); /* Object file version */
+ bswap32s(&ehdr->e_entry); /* Entry point virtual address */
+ bswap32s(&ehdr->e_phoff); /* Program header table file offset */
+ bswap32s(&ehdr->e_shoff); /* Section header table file offset */
+ bswap32s(&ehdr->e_flags); /* Processor-specific flags */
+ bswap16s(&ehdr->e_ehsize); /* ELF header size in bytes */
+ bswap16s(&ehdr->e_phentsize); /* Program header table entry size */
+ bswap16s(&ehdr->e_phnum); /* Program header table entry count */
+ bswap16s(&ehdr->e_shentsize); /* Section header table entry size */
+ bswap16s(&ehdr->e_shnum); /* Section header table entry count */
+ bswap16s(&ehdr->e_shstrndx); /* Section header string table index */
+}
+
+static void bswap_phdr(Elf32_Phdr *phdr)
+{
+ bswap32s(&phdr->p_type); /* Segment type */
+ bswap32s(&phdr->p_offset); /* Segment file offset */
+ bswap32s(&phdr->p_vaddr); /* Segment virtual address */
+ bswap32s(&phdr->p_paddr); /* Segment physical address */
+ bswap32s(&phdr->p_filesz); /* Segment size in file */
+ bswap32s(&phdr->p_memsz); /* Segment size in memory */
+ bswap32s(&phdr->p_flags); /* Segment flags */
+ bswap32s(&phdr->p_align); /* Segment alignment */
+}
+
+static void bswap_shdr(Elf32_Shdr *shdr)
+{
+ bswap32s(&shdr->sh_name);
+ bswap32s(&shdr->sh_type);
+ bswap32s(&shdr->sh_flags);
+ bswap32s(&shdr->sh_addr);
+ bswap32s(&shdr->sh_offset);
+ bswap32s(&shdr->sh_size);
+ bswap32s(&shdr->sh_link);
+ bswap32s(&shdr->sh_info);
+ bswap32s(&shdr->sh_addralign);
+ bswap32s(&shdr->sh_entsize);
+}
+
+static void bswap_sym(Elf32_Sym *sym)
+{
+ bswap32s(&sym->st_name);
+ bswap32s(&sym->st_value);
+ bswap32s(&sym->st_size);
+ bswap16s(&sym->st_shndx);
+}
+#else
+#define bswap_ehdr(e) do { } while (0)
+#define bswap_phdr(e) do { } while (0)
+#define bswap_shdr(e) do { } while (0)
+#define bswap_sym(e) do { } while (0)
+#endif
+
+static int find_phdr(struct elfhdr *ehdr, int fd, struct elf_phdr *phdr, uint32_t type)
+{
+ int i, retval;
+
+ retval = lseek(fd, ehdr->e_phoff, SEEK_SET);
+ if (retval < 0)
+ return -1;
+
+ for (i = 0; i < ehdr->e_phnum; i++) {
+ retval = read(fd, phdr, sizeof(*phdr));
+ if (retval < 0)
+ return -1;
+ bswap_phdr(phdr);
+ if (phdr->p_type == type)
+ return 0;
+ }
+ return -1;
+}
+
+static void *find_shdr(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, uint32_t type)
+{
+ int i, retval;
+
+ retval = lseek(fd, ehdr->e_shoff, SEEK_SET);
+ if (retval < 0)
+ return NULL;
+
+ for (i = 0; i < ehdr->e_shnum; i++) {
+ retval = read(fd, shdr, sizeof(*shdr));
+ if (retval < 0)
+ return NULL;
+ bswap_shdr(shdr);
+ if (shdr->sh_type == type)
+ return qemu_malloc(shdr->sh_size);
+ }
+ return NULL;
+}
+
+static int find_strtab(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, struct elf_shdr *symtab)
+{
+ int retval;
+
+ retval = lseek(fd, ehdr->e_shoff + sizeof(struct elf_shdr) * symtab->sh_link, SEEK_SET);
+ if (retval < 0)
+ return -1;
+
+ retval = read(fd, shdr, sizeof(*shdr));
+ if (retval < 0)
+ return -1;
+ bswap_shdr(shdr);
+ if (shdr->sh_type == SHT_STRTAB)
+ return qemu_malloc(shdr->sh_size);;
+ return 0;
+}
+
+static int read_program(int fd, struct elf_phdr *phdr, void *dst)
+{
+ int retval;
+ retval = lseek(fd, 0x4000, SEEK_SET);
+ if (retval < 0)
+ return -1;
+ return read(fd, dst, phdr->p_filesz);
+}
+
+static int read_section(int fd, struct elf_shdr *s, void *dst)
+{
+ int retval;
+
+ retval = lseek(fd, s->sh_offset, SEEK_SET);
+ if (retval < 0)
+ return -1;
+ retval = read(fd, dst, s->sh_size);
+ if (retval < 0)
+ return -1;
+ return 0;
+}
+
+static void *process_section(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, uint32_t type)
+{
+ void *dst;
+
+ dst = find_shdr(ehdr, fd, shdr, type);
+ if (!dst)
+ goto error;
+
+ if (read_section(fd, shdr, dst))
+ goto error;
+ return dst;
+ error:
+ qemu_free(dst);
+ return NULL;
+}
+
+static void *process_strtab(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, struct elf_shdr *symtab)
+{
+ void *dst;
+
+ dst = find_strtab(ehdr, fd, shdr, symtab);
+ if (!dst)
+ goto error;
+
+ if (read_section(fd, shdr, dst))
+ goto error;
+ return dst;
+ error:
+ qemu_free(dst);
+ return NULL;
+}
+
+static void load_symbols(struct elfhdr *ehdr, int fd)
+{
+ struct elf_shdr symtab, strtab;
+ struct elf_sym *syms;
+ int nsyms, i;
+ char *str;
+
+ /* Symbol table */
+ syms = process_section(ehdr, fd, &symtab, SHT_SYMTAB);
+ if (!syms)
+ return;
+
+ nsyms = symtab.sh_size / sizeof(struct elf_sym);
+ for (i = 0; i < nsyms; i++)
+ bswap_sym(&syms[i]);
+
+ /* String table */
+ str = process_strtab(ehdr, fd, &strtab, &symtab);
+ if (!str)
+ goto error_freesyms;
+
+ /* Commit */
+ if (disas_symtab)
+ qemu_free(disas_symtab); /* XXX Merge with old symbols? */
+ if (disas_strtab)
+ qemu_free(disas_strtab);
+ disas_symtab = syms;
+ disas_num_syms = nsyms;
+ disas_strtab = str;
+ return;
+ error_freesyms:
+ qemu_free(syms);
+ return;
+}
+
+int load_elf(const char * filename, uint8_t *addr)
+{
+ struct elfhdr ehdr;
+ struct elf_phdr phdr;
+ int retval, fd;
+
+ fd = open(filename, O_RDONLY | O_BINARY);
+ if (fd < 0)
+ goto error;
+
+ retval = read(fd, &ehdr, sizeof(ehdr));
+ if (retval < 0)
+ goto error;
+
+ bswap_ehdr(&ehdr);
+
+ if (ehdr.e_ident[0] != 0x7f || ehdr.e_ident[1] != 'E'
+ || ehdr.e_ident[2] != 'L' || ehdr.e_ident[3] != 'F'
+ || ehdr.e_machine != EM_SPARC)
+ goto error;
+
+ if (find_phdr(&ehdr, fd, &phdr, PT_LOAD))
+ goto error;
+ retval = read_program(fd, &phdr, addr);
+ if (retval < 0)
+ goto error;
+
+ load_symbols(&ehdr, fd);
+
+ close(fd);
+ return retval;
+ error:
+ close(fd);
+ return -1;
+}
+
+int load_kernel(const char *filename, uint8_t *addr)
+{
+ int fd, size;
+
+ fd = open(filename, O_RDONLY | O_BINARY);
+ if (fd < 0)
+ return -1;
+ /* load 32 bit code */
+ size = read(fd, addr, 16 * 1024 * 1024);
+ if (size < 0)
+ goto fail;
+ close(fd);
+ return size;
+ fail:
+ close(fd);
+ return -1;
+}
+
+typedef struct MAGICState {
+ uint32_t addr;
+ uint32_t saved_addr;
+ int magic_state;
+ char saved_kfn[1024];
+} MAGICState;
+
+static uint32_t magic_mem_readl(void *opaque, target_phys_addr_t addr)
+{
+ int ret;
+ MAGICState *s = opaque;
+
+ if (s->magic_state == 0) {
+ ret = load_elf(s->saved_kfn, (uint8_t *)s->saved_addr);
+ if (ret < 0)
+ ret = load_kernel(s->saved_kfn, (uint8_t *)s->saved_addr);
+ if (ret < 0) {
+ fprintf(stderr, "qemu: could not load kernel '%s'\n",
+ s->saved_kfn);
+ }
+ s->magic_state = 1; /* No more magic */
+ tb_flush();
+ return bswap32(ret);
+ }
+ return 0;
+}
+
+static void magic_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+}
+
+
+static CPUReadMemoryFunc *magic_mem_read[3] = {
+ magic_mem_readl,
+ magic_mem_readl,
+ magic_mem_readl,
+};
+
+static CPUWriteMemoryFunc *magic_mem_write[3] = {
+ magic_mem_writel,
+ magic_mem_writel,
+ magic_mem_writel,
+};
+
+void magic_init(const char *kfn, int kloadaddr, uint32_t addr)
+{
+ int magic_io_memory;
+ MAGICState *s;
+
+ s = qemu_mallocz(sizeof(MAGICState));
+ if (!s)
+ return;
+
+ strcpy(s->saved_kfn, kfn);
+ s->saved_addr = kloadaddr;
+ s->magic_state = 0;
+ s->addr = addr;
+ magic_io_memory = cpu_register_io_memory(0, magic_mem_read, magic_mem_write, s);
+ cpu_register_physical_memory(addr, 4, magic_io_memory);
+}
+
--- /dev/null
+/*
+ * QEMU MC146818 RTC emulation
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+
+//#define DEBUG_CMOS
+
+#define RTC_SECONDS 0
+#define RTC_SECONDS_ALARM 1
+#define RTC_MINUTES 2
+#define RTC_MINUTES_ALARM 3
+#define RTC_HOURS 4
+#define RTC_HOURS_ALARM 5
+#define RTC_ALARM_DONT_CARE 0xC0
+
+#define RTC_DAY_OF_WEEK 6
+#define RTC_DAY_OF_MONTH 7
+#define RTC_MONTH 8
+#define RTC_YEAR 9
+
+#define RTC_REG_A 10
+#define RTC_REG_B 11
+#define RTC_REG_C 12
+#define RTC_REG_D 13
+
+#define REG_A_UIP 0x80
+
+#define REG_B_SET 0x80
+#define REG_B_PIE 0x40
+#define REG_B_AIE 0x20
+#define REG_B_UIE 0x10
+
+struct RTCState {
+ uint8_t cmos_data[128];
+ uint8_t cmos_index;
+ struct tm current_tm;
+ int irq;
+ /* periodic timer */
+ QEMUTimer *periodic_timer;
+ int64_t next_periodic_time;
+ /* second update */
+ int64_t next_second_time;
+ QEMUTimer *second_timer;
+ QEMUTimer *second_timer2;
+};
+
+static void rtc_set_time(RTCState *s);
+static void rtc_copy_date(RTCState *s);
+
+static void rtc_timer_update(RTCState *s, int64_t current_time)
+{
+ int period_code, period;
+ int64_t cur_clock, next_irq_clock;
+
+ period_code = s->cmos_data[RTC_REG_A] & 0x0f;
+ if (period_code != 0 &&
+ (s->cmos_data[RTC_REG_B] & REG_B_PIE)) {
+ if (period_code <= 2)
+ period_code += 7;
+ /* period in 32 Khz cycles */
+ period = 1 << (period_code - 1);
+ /* compute 32 khz clock */
+ cur_clock = muldiv64(current_time, 32768, ticks_per_sec);
+ next_irq_clock = (cur_clock & ~(period - 1)) + period;
+ s->next_periodic_time = muldiv64(next_irq_clock, ticks_per_sec, 32768) + 1;
+ qemu_mod_timer(s->periodic_timer, s->next_periodic_time);
+ } else {
+ qemu_del_timer(s->periodic_timer);
+ }
+}
+
+static void rtc_periodic_timer(void *opaque)
+{
+ RTCState *s = opaque;
+
+ rtc_timer_update(s, s->next_periodic_time);
+ s->cmos_data[RTC_REG_C] |= 0xc0;
+ pic_set_irq(s->irq, 1);
+}
+
+static void cmos_ioport_write(void *opaque, uint32_t addr, uint32_t data)
+{
+ RTCState *s = opaque;
+
+ if ((addr & 1) == 0) {
+ s->cmos_index = data & 0x7f;
+ } else {
+#ifdef DEBUG_CMOS
+ printf("cmos: write index=0x%02x val=0x%02x\n",
+ s->cmos_index, data);
+#endif
+ switch(s->cmos_index) {
+ case RTC_SECONDS_ALARM:
+ case RTC_MINUTES_ALARM:
+ case RTC_HOURS_ALARM:
+ /* XXX: not supported */
+ s->cmos_data[s->cmos_index] = data;
+ break;
+ case RTC_SECONDS:
+ case RTC_MINUTES:
+ case RTC_HOURS:
+ case RTC_DAY_OF_WEEK:
+ case RTC_DAY_OF_MONTH:
+ case RTC_MONTH:
+ case RTC_YEAR:
+ s->cmos_data[s->cmos_index] = data;
+ /* if in set mode, do not update the time */
+ if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
+ rtc_set_time(s);
+ }
+ break;
+ case RTC_REG_A:
+ /* UIP bit is read only */
+ s->cmos_data[RTC_REG_A] = (data & ~REG_A_UIP) |
+ (s->cmos_data[RTC_REG_A] & REG_A_UIP);
+ rtc_timer_update(s, qemu_get_clock(vm_clock));
+ break;
+ case RTC_REG_B:
+ if (data & REG_B_SET) {
+ /* set mode: reset UIP mode */
+ s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
+ data &= ~REG_B_UIE;
+ } else {
+ /* if disabling set mode, update the time */
+ if (s->cmos_data[RTC_REG_B] & REG_B_SET) {
+ rtc_set_time(s);
+ }
+ }
+ s->cmos_data[RTC_REG_B] = data;
+ rtc_timer_update(s, qemu_get_clock(vm_clock));
+ break;
+ case RTC_REG_C:
+ case RTC_REG_D:
+ /* cannot write to them */
+ break;
+ default:
+ s->cmos_data[s->cmos_index] = data;
+ break;
+ }
+ }
+}
+
+static inline int to_bcd(RTCState *s, int a)
+{
+ if (s->cmos_data[RTC_REG_B] & 0x04) {
+ return a;
+ } else {
+ return ((a / 10) << 4) | (a % 10);
+ }
+}
+
+static inline int from_bcd(RTCState *s, int a)
+{
+ if (s->cmos_data[RTC_REG_B] & 0x04) {
+ return a;
+ } else {
+ return ((a >> 4) * 10) + (a & 0x0f);
+ }
+}
+
+static void rtc_set_time(RTCState *s)
+{
+ struct tm *tm = &s->current_tm;
+
+ tm->tm_sec = from_bcd(s, s->cmos_data[RTC_SECONDS]);
+ tm->tm_min = from_bcd(s, s->cmos_data[RTC_MINUTES]);
+ tm->tm_hour = from_bcd(s, s->cmos_data[RTC_HOURS] & 0x7f);
+ if (!(s->cmos_data[RTC_REG_B] & 0x02) &&
+ (s->cmos_data[RTC_HOURS] & 0x80)) {
+ tm->tm_hour += 12;
+ }
+ tm->tm_wday = from_bcd(s, s->cmos_data[RTC_DAY_OF_WEEK]);
+ tm->tm_mday = from_bcd(s, s->cmos_data[RTC_DAY_OF_MONTH]);
+ tm->tm_mon = from_bcd(s, s->cmos_data[RTC_MONTH]) - 1;
+ tm->tm_year = from_bcd(s, s->cmos_data[RTC_YEAR]) + 100;
+}
+
+static void rtc_copy_date(RTCState *s)
+{
+ const struct tm *tm = &s->current_tm;
+
+ s->cmos_data[RTC_SECONDS] = to_bcd(s, tm->tm_sec);
+ s->cmos_data[RTC_MINUTES] = to_bcd(s, tm->tm_min);
+ if (s->cmos_data[RTC_REG_B] & 0x02) {
+ /* 24 hour format */
+ s->cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour);
+ } else {
+ /* 12 hour format */
+ s->cmos_data[RTC_HOURS] = to_bcd(s, tm->tm_hour % 12);
+ if (tm->tm_hour >= 12)
+ s->cmos_data[RTC_HOURS] |= 0x80;
+ }
+ s->cmos_data[RTC_DAY_OF_WEEK] = to_bcd(s, tm->tm_wday);
+ s->cmos_data[RTC_DAY_OF_MONTH] = to_bcd(s, tm->tm_mday);
+ s->cmos_data[RTC_MONTH] = to_bcd(s, tm->tm_mon + 1);
+ s->cmos_data[RTC_YEAR] = to_bcd(s, tm->tm_year % 100);
+}
+
+/* month is between 0 and 11. */
+static int get_days_in_month(int month, int year)
+{
+ static const int days_tab[12] = {
+ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
+ };
+ int d;
+ if ((unsigned )month >= 12)
+ return 31;
+ d = days_tab[month];
+ if (month == 1) {
+ if ((year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0))
+ d++;
+ }
+ return d;
+}
+
+/* update 'tm' to the next second */
+static void rtc_next_second(struct tm *tm)
+{
+ int days_in_month;
+
+ tm->tm_sec++;
+ if ((unsigned)tm->tm_sec >= 60) {
+ tm->tm_sec = 0;
+ tm->tm_min++;
+ if ((unsigned)tm->tm_min >= 60) {
+ tm->tm_min = 0;
+ tm->tm_hour++;
+ if ((unsigned)tm->tm_hour >= 24) {
+ tm->tm_hour = 0;
+ /* next day */
+ tm->tm_wday++;
+ if ((unsigned)tm->tm_wday >= 7)
+ tm->tm_wday = 0;
+ days_in_month = get_days_in_month(tm->tm_mon,
+ tm->tm_year + 1900);
+ tm->tm_mday++;
+ if (tm->tm_mday < 1) {
+ tm->tm_mday = 1;
+ } else if (tm->tm_mday > days_in_month) {
+ tm->tm_mday = 1;
+ tm->tm_mon++;
+ if (tm->tm_mon >= 12) {
+ tm->tm_mon = 0;
+ tm->tm_year++;
+ }
+ }
+ }
+ }
+ }
+}
+
+
+static void rtc_update_second(void *opaque)
+{
+ RTCState *s = opaque;
+ int64_t delay;
+
+ /* if the oscillator is not in normal operation, we do not update */
+ if ((s->cmos_data[RTC_REG_A] & 0x70) != 0x20) {
+ s->next_second_time += ticks_per_sec;
+ qemu_mod_timer(s->second_timer, s->next_second_time);
+ } else {
+ rtc_next_second(&s->current_tm);
+
+ if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
+ /* update in progress bit */
+ s->cmos_data[RTC_REG_A] |= REG_A_UIP;
+ }
+ /* should be 244 us = 8 / 32768 seconds, but currently the
+ timers do not have the necessary resolution. */
+ delay = (ticks_per_sec * 1) / 100;
+ if (delay < 1)
+ delay = 1;
+ qemu_mod_timer(s->second_timer2,
+ s->next_second_time + delay);
+ }
+}
+
+static void rtc_update_second2(void *opaque)
+{
+ RTCState *s = opaque;
+
+ if (!(s->cmos_data[RTC_REG_B] & REG_B_SET)) {
+ rtc_copy_date(s);
+ }
+
+ /* check alarm */
+ if (s->cmos_data[RTC_REG_B] & REG_B_AIE) {
+ if (((s->cmos_data[RTC_SECONDS_ALARM] & 0xc0) == 0xc0 ||
+ s->cmos_data[RTC_SECONDS_ALARM] == s->current_tm.tm_sec) &&
+ ((s->cmos_data[RTC_MINUTES_ALARM] & 0xc0) == 0xc0 ||
+ s->cmos_data[RTC_MINUTES_ALARM] == s->current_tm.tm_mon) &&
+ ((s->cmos_data[RTC_HOURS_ALARM] & 0xc0) == 0xc0 ||
+ s->cmos_data[RTC_HOURS_ALARM] == s->current_tm.tm_hour)) {
+
+ s->cmos_data[RTC_REG_C] |= 0xa0;
+ pic_set_irq(s->irq, 1);
+ }
+ }
+
+ /* update ended interrupt */
+ if (s->cmos_data[RTC_REG_B] & REG_B_UIE) {
+ s->cmos_data[RTC_REG_C] |= 0x90;
+ pic_set_irq(s->irq, 1);
+ }
+
+ /* clear update in progress bit */
+ s->cmos_data[RTC_REG_A] &= ~REG_A_UIP;
+
+ s->next_second_time += ticks_per_sec;
+ qemu_mod_timer(s->second_timer, s->next_second_time);
+}
+
+static uint32_t cmos_ioport_read(void *opaque, uint32_t addr)
+{
+ RTCState *s = opaque;
+ int ret;
+ if ((addr & 1) == 0) {
+ return 0xff;
+ } else {
+ switch(s->cmos_index) {
+ case RTC_SECONDS:
+ case RTC_MINUTES:
+ case RTC_HOURS:
+ case RTC_DAY_OF_WEEK:
+ case RTC_DAY_OF_MONTH:
+ case RTC_MONTH:
+ case RTC_YEAR:
+ ret = s->cmos_data[s->cmos_index];
+ break;
+ case RTC_REG_A:
+ ret = s->cmos_data[s->cmos_index];
+ break;
+ case RTC_REG_C:
+ ret = s->cmos_data[s->cmos_index];
+ pic_set_irq(s->irq, 0);
+ s->cmos_data[RTC_REG_C] = 0x00;
+ break;
+ default:
+ ret = s->cmos_data[s->cmos_index];
+ break;
+ }
+#ifdef DEBUG_CMOS
+ printf("cmos: read index=0x%02x val=0x%02x\n",
+ s->cmos_index, ret);
+#endif
+ return ret;
+ }
+}
+
+void rtc_set_memory(RTCState *s, int addr, int val)
+{
+ if (addr >= 0 && addr <= 127)
+ s->cmos_data[addr] = val;
+}
+
+void rtc_set_date(RTCState *s, const struct tm *tm)
+{
+ s->current_tm = *tm;
+ rtc_copy_date(s);
+}
+
+static void rtc_save(QEMUFile *f, void *opaque)
+{
+ RTCState *s = opaque;
+
+ qemu_put_buffer(f, s->cmos_data, 128);
+ qemu_put_8s(f, &s->cmos_index);
+
+ qemu_put_be32s(f, &s->current_tm.tm_sec);
+ qemu_put_be32s(f, &s->current_tm.tm_min);
+ qemu_put_be32s(f, &s->current_tm.tm_hour);
+ qemu_put_be32s(f, &s->current_tm.tm_wday);
+ qemu_put_be32s(f, &s->current_tm.tm_mday);
+ qemu_put_be32s(f, &s->current_tm.tm_mon);
+ qemu_put_be32s(f, &s->current_tm.tm_year);
+
+ qemu_put_timer(f, s->periodic_timer);
+ qemu_put_be64s(f, &s->next_periodic_time);
+
+ qemu_put_be64s(f, &s->next_second_time);
+ qemu_put_timer(f, s->second_timer);
+ qemu_put_timer(f, s->second_timer2);
+}
+
+static int rtc_load(QEMUFile *f, void *opaque, int version_id)
+{
+ RTCState *s = opaque;
+
+ if (version_id != 1)
+ return -EINVAL;
+
+ qemu_get_buffer(f, s->cmos_data, 128);
+ qemu_get_8s(f, &s->cmos_index);
+
+ qemu_get_be32s(f, &s->current_tm.tm_sec);
+ qemu_get_be32s(f, &s->current_tm.tm_min);
+ qemu_get_be32s(f, &s->current_tm.tm_hour);
+ qemu_get_be32s(f, &s->current_tm.tm_wday);
+ qemu_get_be32s(f, &s->current_tm.tm_mday);
+ qemu_get_be32s(f, &s->current_tm.tm_mon);
+ qemu_get_be32s(f, &s->current_tm.tm_year);
+
+ qemu_get_timer(f, s->periodic_timer);
+ qemu_get_be64s(f, &s->next_periodic_time);
+
+ qemu_get_be64s(f, &s->next_second_time);
+ qemu_get_timer(f, s->second_timer);
+ qemu_get_timer(f, s->second_timer2);
+ return 0;
+}
+
+RTCState *rtc_init(int base, int irq)
+{
+ RTCState *s;
+
+ s = qemu_mallocz(sizeof(RTCState));
+ if (!s)
+ return NULL;
+
+ s->irq = irq;
+ s->cmos_data[RTC_REG_A] = 0x26;
+ s->cmos_data[RTC_REG_B] = 0x02;
+ s->cmos_data[RTC_REG_C] = 0x00;
+ s->cmos_data[RTC_REG_D] = 0x80;
+
+ s->periodic_timer = qemu_new_timer(vm_clock,
+ rtc_periodic_timer, s);
+ s->second_timer = qemu_new_timer(vm_clock,
+ rtc_update_second, s);
+ s->second_timer2 = qemu_new_timer(vm_clock,
+ rtc_update_second2, s);
+
+ s->next_second_time = qemu_get_clock(vm_clock) + (ticks_per_sec * 99) / 100;
+ qemu_mod_timer(s->second_timer2, s->next_second_time);
+
+ register_ioport_write(base, 2, 1, cmos_ioport_write, s);
+ register_ioport_read(base, 2, 1, cmos_ioport_read, s);
+
+ register_savevm("mc146818rtc", base, 1, rtc_save, rtc_load, s);
+ return s;
+}
+
--- /dev/null
+/*
+ * QEMU NE2000 emulation
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+
+/* debug NE2000 card */
+//#define DEBUG_NE2000
+
+#define MAX_ETH_FRAME_SIZE 1514
+
+#define E8390_CMD 0x00 /* The command register (for all pages) */
+/* Page 0 register offsets. */
+#define EN0_CLDALO 0x01 /* Low byte of current local dma addr RD */
+#define EN0_STARTPG 0x01 /* Starting page of ring bfr WR */
+#define EN0_CLDAHI 0x02 /* High byte of current local dma addr RD */
+#define EN0_STOPPG 0x02 /* Ending page +1 of ring bfr WR */
+#define EN0_BOUNDARY 0x03 /* Boundary page of ring bfr RD WR */
+#define EN0_TSR 0x04 /* Transmit status reg RD */
+#define EN0_TPSR 0x04 /* Transmit starting page WR */
+#define EN0_NCR 0x05 /* Number of collision reg RD */
+#define EN0_TCNTLO 0x05 /* Low byte of tx byte count WR */
+#define EN0_FIFO 0x06 /* FIFO RD */
+#define EN0_TCNTHI 0x06 /* High byte of tx byte count WR */
+#define EN0_ISR 0x07 /* Interrupt status reg RD WR */
+#define EN0_CRDALO 0x08 /* low byte of current remote dma address RD */
+#define EN0_RSARLO 0x08 /* Remote start address reg 0 */
+#define EN0_CRDAHI 0x09 /* high byte, current remote dma address RD */
+#define EN0_RSARHI 0x09 /* Remote start address reg 1 */
+#define EN0_RCNTLO 0x0a /* Remote byte count reg WR */
+#define EN0_RCNTHI 0x0b /* Remote byte count reg WR */
+#define EN0_RSR 0x0c /* rx status reg RD */
+#define EN0_RXCR 0x0c /* RX configuration reg WR */
+#define EN0_TXCR 0x0d /* TX configuration reg WR */
+#define EN0_COUNTER0 0x0d /* Rcv alignment error counter RD */
+#define EN0_DCFG 0x0e /* Data configuration reg WR */
+#define EN0_COUNTER1 0x0e /* Rcv CRC error counter RD */
+#define EN0_IMR 0x0f /* Interrupt mask reg WR */
+#define EN0_COUNTER2 0x0f /* Rcv missed frame error counter RD */
+
+#define EN1_PHYS 0x11
+#define EN1_CURPAG 0x17
+#define EN1_MULT 0x18
+
+/* Register accessed at EN_CMD, the 8390 base addr. */
+#define E8390_STOP 0x01 /* Stop and reset the chip */
+#define E8390_START 0x02 /* Start the chip, clear reset */
+#define E8390_TRANS 0x04 /* Transmit a frame */
+#define E8390_RREAD 0x08 /* Remote read */
+#define E8390_RWRITE 0x10 /* Remote write */
+#define E8390_NODMA 0x20 /* Remote DMA */
+#define E8390_PAGE0 0x00 /* Select page chip registers */
+#define E8390_PAGE1 0x40 /* using the two high-order bits */
+#define E8390_PAGE2 0x80 /* Page 3 is invalid. */
+
+/* Bits in EN0_ISR - Interrupt status register */
+#define ENISR_RX 0x01 /* Receiver, no error */
+#define ENISR_TX 0x02 /* Transmitter, no error */
+#define ENISR_RX_ERR 0x04 /* Receiver, with error */
+#define ENISR_TX_ERR 0x08 /* Transmitter, with error */
+#define ENISR_OVER 0x10 /* Receiver overwrote the ring */
+#define ENISR_COUNTERS 0x20 /* Counters need emptying */
+#define ENISR_RDC 0x40 /* remote dma complete */
+#define ENISR_RESET 0x80 /* Reset completed */
+#define ENISR_ALL 0x3f /* Interrupts we will enable */
+
+/* Bits in received packet status byte and EN0_RSR*/
+#define ENRSR_RXOK 0x01 /* Received a good packet */
+#define ENRSR_CRC 0x02 /* CRC error */
+#define ENRSR_FAE 0x04 /* frame alignment error */
+#define ENRSR_FO 0x08 /* FIFO overrun */
+#define ENRSR_MPA 0x10 /* missed pkt */
+#define ENRSR_PHY 0x20 /* physical/multicast address */
+#define ENRSR_DIS 0x40 /* receiver disable. set in monitor mode */
+#define ENRSR_DEF 0x80 /* deferring */
+
+/* Transmitted packet status, EN0_TSR. */
+#define ENTSR_PTX 0x01 /* Packet transmitted without error */
+#define ENTSR_ND 0x02 /* The transmit wasn't deferred. */
+#define ENTSR_COL 0x04 /* The transmit collided at least once. */
+#define ENTSR_ABT 0x08 /* The transmit collided 16 times, and was deferred. */
+#define ENTSR_CRS 0x10 /* The carrier sense was lost. */
+#define ENTSR_FU 0x20 /* A "FIFO underrun" occurred during transmit. */
+#define ENTSR_CDH 0x40 /* The collision detect "heartbeat" signal was lost. */
+#define ENTSR_OWC 0x80 /* There was an out-of-window collision. */
+
+#define NE2000_PMEM_SIZE (32*1024)
+#define NE2000_PMEM_START (16*1024)
+#define NE2000_PMEM_END (NE2000_PMEM_SIZE+NE2000_PMEM_START)
+#define NE2000_MEM_SIZE NE2000_PMEM_END
+
+typedef struct NE2000State {
+ uint8_t cmd;
+ uint32_t start;
+ uint32_t stop;
+ uint8_t boundary;
+ uint8_t tsr;
+ uint8_t tpsr;
+ uint16_t tcnt;
+ uint16_t rcnt;
+ uint32_t rsar;
+ uint8_t rsr;
+ uint8_t isr;
+ uint8_t dcfg;
+ uint8_t imr;
+ uint8_t phys[6]; /* mac address */
+ uint8_t curpag;
+ uint8_t mult[8]; /* multicast mask array */
+ int irq;
+ PCIDevice *pci_dev;
+ NetDriverState *nd;
+ uint8_t mem[NE2000_MEM_SIZE];
+} NE2000State;
+
+static void ne2000_reset(NE2000State *s)
+{
+ int i;
+
+ s->isr = ENISR_RESET;
+ memcpy(s->mem, s->nd->macaddr, 6);
+ s->mem[14] = 0x57;
+ s->mem[15] = 0x57;
+
+ /* duplicate prom data */
+ for(i = 15;i >= 0; i--) {
+ s->mem[2 * i] = s->mem[i];
+ s->mem[2 * i + 1] = s->mem[i];
+ }
+}
+
+static void ne2000_update_irq(NE2000State *s)
+{
+ int isr;
+ isr = s->isr & s->imr;
+#if defined(DEBUG_NE2000)
+ printf("NE2000: Set IRQ line %d to %d (%02x %02x)\n",
+ s->irq, isr ? 1 : 0, s->isr, s->imr);
+#endif
+ if (s->irq == 16) {
+ /* PCI irq */
+ pci_set_irq(s->pci_dev, 0, (isr != 0));
+ } else {
+ /* ISA irq */
+ pic_set_irq(s->irq, (isr != 0));
+ }
+}
+
+/* return the max buffer size if the NE2000 can receive more data */
+static int ne2000_can_receive(void *opaque)
+{
+ NE2000State *s = opaque;
+ int avail, index, boundary;
+
+ if (s->cmd & E8390_STOP)
+ return 0;
+ index = s->curpag << 8;
+ boundary = s->boundary << 8;
+ if (index < boundary)
+ avail = boundary - index;
+ else
+ avail = (s->stop - s->start) - (index - boundary);
+ if (avail < (MAX_ETH_FRAME_SIZE + 4))
+ return 0;
+ return MAX_ETH_FRAME_SIZE;
+}
+
+#define MIN_BUF_SIZE 60
+
+static void ne2000_receive(void *opaque, const uint8_t *buf, int size)
+{
+ NE2000State *s = opaque;
+ uint8_t *p;
+ int total_len, next, avail, len, index;
+ uint8_t buf1[60];
+
+#if defined(DEBUG_NE2000)
+ printf("NE2000: received len=%d\n", size);
+#endif
+
+ /* if too small buffer, then expand it */
+ if (size < MIN_BUF_SIZE) {
+ memcpy(buf1, buf, size);
+ memset(buf1 + size, 0, MIN_BUF_SIZE - size);
+ buf = buf1;
+ size = MIN_BUF_SIZE;
+ }
+
+ index = s->curpag << 8;
+ /* 4 bytes for header */
+ total_len = size + 4;
+ /* address for next packet (4 bytes for CRC) */
+ next = index + ((total_len + 4 + 255) & ~0xff);
+ if (next >= s->stop)
+ next -= (s->stop - s->start);
+ /* prepare packet header */
+ p = s->mem + index;
+ s->rsr = ENRSR_RXOK; /* receive status */
+ /* XXX: check this */
+ if (buf[0] & 0x01)
+ s->rsr |= ENRSR_PHY;
+ p[0] = s->rsr;
+ p[1] = next >> 8;
+ p[2] = total_len;
+ p[3] = total_len >> 8;
+ index += 4;
+
+ /* write packet data */
+ while (size > 0) {
+ avail = s->stop - index;
+ len = size;
+ if (len > avail)
+ len = avail;
+ memcpy(s->mem + index, buf, len);
+ buf += len;
+ index += len;
+ if (index == s->stop)
+ index = s->start;
+ size -= len;
+ }
+ s->curpag = next >> 8;
+
+ /* now we can signal we have receive something */
+ s->isr |= ENISR_RX;
+ ne2000_update_irq(s);
+}
+
+static void ne2000_ioport_write(void *opaque, uint32_t addr, uint32_t val)
+{
+ NE2000State *s = opaque;
+ int offset, page;
+
+ addr &= 0xf;
+#ifdef DEBUG_NE2000
+ printf("NE2000: write addr=0x%x val=0x%02x\n", addr, val);
+#endif
+ if (addr == E8390_CMD) {
+ /* control register */
+ s->cmd = val;
+ if (val & E8390_START) {
+ s->isr &= ~ENISR_RESET;
+ /* test specific case: zero length transfert */
+ if ((val & (E8390_RREAD | E8390_RWRITE)) &&
+ s->rcnt == 0) {
+ s->isr |= ENISR_RDC;
+ ne2000_update_irq(s);
+ }
+ if (val & E8390_TRANS) {
+ qemu_send_packet(s->nd, s->mem + (s->tpsr << 8), s->tcnt);
+ /* signal end of transfert */
+ s->tsr = ENTSR_PTX;
+ s->isr |= ENISR_TX;
+ ne2000_update_irq(s);
+ }
+ }
+ } else {
+ page = s->cmd >> 6;
+ offset = addr | (page << 4);
+ switch(offset) {
+ case EN0_STARTPG:
+ s->start = val << 8;
+ break;
+ case EN0_STOPPG:
+ s->stop = val << 8;
+ break;
+ case EN0_BOUNDARY:
+ s->boundary = val;
+ break;
+ case EN0_IMR:
+ s->imr = val;
+ ne2000_update_irq(s);
+ break;
+ case EN0_TPSR:
+ s->tpsr = val;
+ break;
+ case EN0_TCNTLO:
+ s->tcnt = (s->tcnt & 0xff00) | val;
+ break;
+ case EN0_TCNTHI:
+ s->tcnt = (s->tcnt & 0x00ff) | (val << 8);
+ break;
+ case EN0_RSARLO:
+ s->rsar = (s->rsar & 0xff00) | val;
+ break;
+ case EN0_RSARHI:
+ s->rsar = (s->rsar & 0x00ff) | (val << 8);
+ break;
+ case EN0_RCNTLO:
+ s->rcnt = (s->rcnt & 0xff00) | val;
+ break;
+ case EN0_RCNTHI:
+ s->rcnt = (s->rcnt & 0x00ff) | (val << 8);
+ break;
+ case EN0_DCFG:
+ s->dcfg = val;
+ break;
+ case EN0_ISR:
+ s->isr &= ~(val & 0x7f);
+ ne2000_update_irq(s);
+ break;
+ case EN1_PHYS ... EN1_PHYS + 5:
+ s->phys[offset - EN1_PHYS] = val;
+ break;
+ case EN1_CURPAG:
+ s->curpag = val;
+ break;
+ case EN1_MULT ... EN1_MULT + 7:
+ s->mult[offset - EN1_MULT] = val;
+ break;
+ }
+ }
+}
+
+static uint32_t ne2000_ioport_read(void *opaque, uint32_t addr)
+{
+ NE2000State *s = opaque;
+ int offset, page, ret;
+
+ addr &= 0xf;
+ if (addr == E8390_CMD) {
+ ret = s->cmd;
+ } else {
+ page = s->cmd >> 6;
+ offset = addr | (page << 4);
+ switch(offset) {
+ case EN0_TSR:
+ ret = s->tsr;
+ break;
+ case EN0_BOUNDARY:
+ ret = s->boundary;
+ break;
+ case EN0_ISR:
+ ret = s->isr;
+ break;
+ case EN0_RSARLO:
+ ret = s->rsar & 0x00ff;
+ break;
+ case EN0_RSARHI:
+ ret = s->rsar >> 8;
+ break;
+ case EN1_PHYS ... EN1_PHYS + 5:
+ ret = s->phys[offset - EN1_PHYS];
+ break;
+ case EN1_CURPAG:
+ ret = s->curpag;
+ break;
+ case EN1_MULT ... EN1_MULT + 7:
+ ret = s->mult[offset - EN1_MULT];
+ break;
+ case EN0_RSR:
+ ret = s->rsr;
+ break;
+ default:
+ ret = 0x00;
+ break;
+ }
+ }
+#ifdef DEBUG_NE2000
+ printf("NE2000: read addr=0x%x val=%02x\n", addr, ret);
+#endif
+ return ret;
+}
+
+static inline void ne2000_mem_writeb(NE2000State *s, uint32_t addr,
+ uint32_t val)
+{
+ if (addr < 32 ||
+ (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
+ s->mem[addr] = val;
+ }
+}
+
+static inline void ne2000_mem_writew(NE2000State *s, uint32_t addr,
+ uint32_t val)
+{
+ addr &= ~1; /* XXX: check exact behaviour if not even */
+ if (addr < 32 ||
+ (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
+ *(uint16_t *)(s->mem + addr) = cpu_to_le16(val);
+ }
+}
+
+static inline void ne2000_mem_writel(NE2000State *s, uint32_t addr,
+ uint32_t val)
+{
+ addr &= ~1; /* XXX: check exact behaviour if not even */
+ if (addr < 32 ||
+ (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
+ cpu_to_le32wu((uint32_t *)(s->mem + addr), val);
+ }
+}
+
+static inline uint32_t ne2000_mem_readb(NE2000State *s, uint32_t addr)
+{
+ if (addr < 32 ||
+ (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
+ return s->mem[addr];
+ } else {
+ return 0xff;
+ }
+}
+
+static inline uint32_t ne2000_mem_readw(NE2000State *s, uint32_t addr)
+{
+ addr &= ~1; /* XXX: check exact behaviour if not even */
+ if (addr < 32 ||
+ (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
+ return le16_to_cpu(*(uint16_t *)(s->mem + addr));
+ } else {
+ return 0xffff;
+ }
+}
+
+static inline uint32_t ne2000_mem_readl(NE2000State *s, uint32_t addr)
+{
+ addr &= ~1; /* XXX: check exact behaviour if not even */
+ if (addr < 32 ||
+ (addr >= NE2000_PMEM_START && addr < NE2000_MEM_SIZE)) {
+ return le32_to_cpupu((uint32_t *)(s->mem + addr));
+ } else {
+ return 0xffffffff;
+ }
+}
+
+static inline void ne2000_dma_update(NE2000State *s, int len)
+{
+ s->rsar += len;
+ /* wrap */
+ /* XXX: check what to do if rsar > stop */
+ if (s->rsar == s->stop)
+ s->rsar = s->start;
+
+ if (s->rcnt <= len) {
+ s->rcnt = 0;
+ /* signal end of transfert */
+ s->isr |= ENISR_RDC;
+ ne2000_update_irq(s);
+ } else {
+ s->rcnt -= len;
+ }
+}
+
+static void ne2000_asic_ioport_write(void *opaque, uint32_t addr, uint32_t val)
+{
+ NE2000State *s = opaque;
+
+#ifdef DEBUG_NE2000
+ printf("NE2000: asic write val=0x%04x\n", val);
+#endif
+ if (s->rcnt == 0)
+ return;
+ if (s->dcfg & 0x01) {
+ /* 16 bit access */
+ ne2000_mem_writew(s, s->rsar, val);
+ ne2000_dma_update(s, 2);
+ } else {
+ /* 8 bit access */
+ ne2000_mem_writeb(s, s->rsar, val);
+ ne2000_dma_update(s, 1);
+ }
+}
+
+static uint32_t ne2000_asic_ioport_read(void *opaque, uint32_t addr)
+{
+ NE2000State *s = opaque;
+ int ret;
+
+ if (s->dcfg & 0x01) {
+ /* 16 bit access */
+ ret = ne2000_mem_readw(s, s->rsar);
+ ne2000_dma_update(s, 2);
+ } else {
+ /* 8 bit access */
+ ret = ne2000_mem_readb(s, s->rsar);
+ ne2000_dma_update(s, 1);
+ }
+#ifdef DEBUG_NE2000
+ printf("NE2000: asic read val=0x%04x\n", ret);
+#endif
+ return ret;
+}
+
+static void ne2000_asic_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
+{
+ NE2000State *s = opaque;
+
+#ifdef DEBUG_NE2000
+ printf("NE2000: asic writel val=0x%04x\n", val);
+#endif
+ if (s->rcnt == 0)
+ return;
+ /* 32 bit access */
+ ne2000_mem_writel(s, s->rsar, val);
+ ne2000_dma_update(s, 4);
+}
+
+static uint32_t ne2000_asic_ioport_readl(void *opaque, uint32_t addr)
+{
+ NE2000State *s = opaque;
+ int ret;
+
+ /* 32 bit access */
+ ret = ne2000_mem_readl(s, s->rsar);
+ ne2000_dma_update(s, 4);
+#ifdef DEBUG_NE2000
+ printf("NE2000: asic readl val=0x%04x\n", ret);
+#endif
+ return ret;
+}
+
+static void ne2000_reset_ioport_write(void *opaque, uint32_t addr, uint32_t val)
+{
+ /* nothing to do (end of reset pulse) */
+}
+
+static uint32_t ne2000_reset_ioport_read(void *opaque, uint32_t addr)
+{
+ NE2000State *s = opaque;
+ ne2000_reset(s);
+ return 0;
+}
+
+static void ne2000_save(QEMUFile* f,void* opaque)
+{
+ NE2000State* s=(NE2000State*)opaque;
+
+ qemu_put_8s(f, &s->cmd);
+ qemu_put_be32s(f, &s->start);
+ qemu_put_be32s(f, &s->stop);
+ qemu_put_8s(f, &s->boundary);
+ qemu_put_8s(f, &s->tsr);
+ qemu_put_8s(f, &s->tpsr);
+ qemu_put_be16s(f, &s->tcnt);
+ qemu_put_be16s(f, &s->rcnt);
+ qemu_put_be32s(f, &s->rsar);
+ qemu_put_8s(f, &s->rsr);
+ qemu_put_8s(f, &s->isr);
+ qemu_put_8s(f, &s->dcfg);
+ qemu_put_8s(f, &s->imr);
+ qemu_put_buffer(f, s->phys, 6);
+ qemu_put_8s(f, &s->curpag);
+ qemu_put_buffer(f, s->mult, 8);
+ qemu_put_be32s(f, &s->irq);
+ qemu_put_buffer(f, s->mem, NE2000_MEM_SIZE);
+}
+
+static int ne2000_load(QEMUFile* f,void* opaque,int version_id)
+{
+ NE2000State* s=(NE2000State*)opaque;
+
+ if (version_id != 1)
+ return -EINVAL;
+
+ qemu_get_8s(f, &s->cmd);
+ qemu_get_be32s(f, &s->start);
+ qemu_get_be32s(f, &s->stop);
+ qemu_get_8s(f, &s->boundary);
+ qemu_get_8s(f, &s->tsr);
+ qemu_get_8s(f, &s->tpsr);
+ qemu_get_be16s(f, &s->tcnt);
+ qemu_get_be16s(f, &s->rcnt);
+ qemu_get_be32s(f, &s->rsar);
+ qemu_get_8s(f, &s->rsr);
+ qemu_get_8s(f, &s->isr);
+ qemu_get_8s(f, &s->dcfg);
+ qemu_get_8s(f, &s->imr);
+ qemu_get_buffer(f, s->phys, 6);
+ qemu_get_8s(f, &s->curpag);
+ qemu_get_buffer(f, s->mult, 8);
+ qemu_get_be32s(f, &s->irq);
+ qemu_get_buffer(f, s->mem, NE2000_MEM_SIZE);
+
+ return 0;
+}
+
+void isa_ne2000_init(int base, int irq, NetDriverState *nd)
+{
+ NE2000State *s;
+
+ s = qemu_mallocz(sizeof(NE2000State));
+ if (!s)
+ return;
+
+ register_ioport_write(base, 16, 1, ne2000_ioport_write, s);
+ register_ioport_read(base, 16, 1, ne2000_ioport_read, s);
+
+ register_ioport_write(base + 0x10, 1, 1, ne2000_asic_ioport_write, s);
+ register_ioport_read(base + 0x10, 1, 1, ne2000_asic_ioport_read, s);
+ register_ioport_write(base + 0x10, 2, 2, ne2000_asic_ioport_write, s);
+ register_ioport_read(base + 0x10, 2, 2, ne2000_asic_ioport_read, s);
+
+ register_ioport_write(base + 0x1f, 1, 1, ne2000_reset_ioport_write, s);
+ register_ioport_read(base + 0x1f, 1, 1, ne2000_reset_ioport_read, s);
+ s->irq = irq;
+ s->nd = nd;
+
+ ne2000_reset(s);
+
+ qemu_add_read_packet(nd, ne2000_can_receive, ne2000_receive, s);
+
+ register_savevm("ne2000", 0, 1, ne2000_save, ne2000_load, s);
+
+}
+
+/***********************************************************/
+/* PCI NE2000 definitions */
+
+typedef struct PCINE2000State {
+ PCIDevice dev;
+ NE2000State ne2000;
+} PCINE2000State;
+
+static void ne2000_map(PCIDevice *pci_dev, int region_num,
+ uint32_t addr, uint32_t size, int type)
+{
+ PCINE2000State *d = (PCINE2000State *)pci_dev;
+ NE2000State *s = &d->ne2000;
+
+ register_ioport_write(addr, 16, 1, ne2000_ioport_write, s);
+ register_ioport_read(addr, 16, 1, ne2000_ioport_read, s);
+
+ register_ioport_write(addr + 0x10, 1, 1, ne2000_asic_ioport_write, s);
+ register_ioport_read(addr + 0x10, 1, 1, ne2000_asic_ioport_read, s);
+ register_ioport_write(addr + 0x10, 2, 2, ne2000_asic_ioport_write, s);
+ register_ioport_read(addr + 0x10, 2, 2, ne2000_asic_ioport_read, s);
+ register_ioport_write(addr + 0x10, 4, 4, ne2000_asic_ioport_writel, s);
+ register_ioport_read(addr + 0x10, 4, 4, ne2000_asic_ioport_readl, s);
+
+ register_ioport_write(addr + 0x1f, 1, 1, ne2000_reset_ioport_write, s);
+ register_ioport_read(addr + 0x1f, 1, 1, ne2000_reset_ioport_read, s);
+}
+
+void pci_ne2000_init(PCIBus *bus, NetDriverState *nd)
+{
+ PCINE2000State *d;
+ NE2000State *s;
+ uint8_t *pci_conf;
+
+ d = (PCINE2000State *)pci_register_device(bus,
+ "NE2000", sizeof(PCINE2000State),
+ -1,
+ NULL, NULL);
+ pci_conf = d->dev.config;
+ pci_conf[0x00] = 0xec; // Realtek 8029
+ pci_conf[0x01] = 0x10;
+ pci_conf[0x02] = 0x29;
+ pci_conf[0x03] = 0x80;
+ pci_conf[0x0a] = 0x00; // ethernet network controller
+ pci_conf[0x0b] = 0x02;
+ pci_conf[0x0e] = 0x00; // header_type
+ pci_conf[0x3d] = 1; // interrupt pin 0
+
+ pci_register_io_region(&d->dev, 0, 0x100,
+ PCI_ADDRESS_SPACE_IO, ne2000_map);
+ s = &d->ne2000;
+ s->irq = 16; // PCI interrupt
+ s->pci_dev = (PCIDevice *)d;
+ s->nd = nd;
+ ne2000_reset(s);
+ qemu_add_read_packet(nd, ne2000_can_receive, ne2000_receive, s);
+
+ /* XXX: instance number ? */
+ register_savevm("ne2000", 0, 1, ne2000_save, ne2000_load, s);
+ register_savevm("ne2000_pci", 0, 1, generic_pci_save, generic_pci_load,
+ &d->dev);
+}
--- /dev/null
+/*
+ * OpenPIC emulation
+ *
+ * Copyright (c) 2004 Jocelyn Mayer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+/*
+ *
+ * Based on OpenPic implementations:
+ * - Intel GW80314 I/O compagnion chip developper's manual
+ * - Motorola MPC8245 & MPC8540 user manuals.
+ * - Motorola MCP750 (aka Raven) programmer manual.
+ * - Motorola Harrier programmer manuel
+ *
+ * Serial interrupts, as implemented in Raven chipset are not supported yet.
+ *
+ */
+#include "vl.h"
+
+//#define DEBUG_OPENPIC
+
+#ifdef DEBUG_OPENPIC
+#define DPRINTF(fmt, args...) do { printf(fmt , ##args); } while (0)
+#else
+#define DPRINTF(fmt, args...) do { } while (0)
+#endif
+#define ERROR(fmr, args...) do { printf("ERROR: " fmr , ##args); } while (0)
+
+#define USE_MPCxxx /* Intel model is broken, for now */
+
+#if defined (USE_INTEL_GW80314)
+/* Intel GW80314 I/O Companion chip */
+
+#define MAX_CPU 4
+#define MAX_IRQ 32
+#define MAX_DBL 4
+#define MAX_MBX 4
+#define MAX_TMR 4
+#define VECTOR_BITS 8
+#define MAX_IPI 0
+
+#define VID (0x00000000)
+
+#define OPENPIC_LITTLE_ENDIAN 1
+#define OPENPIC_BIG_ENDIAN 0
+
+#elif defined(USE_MPCxxx)
+
+#define MAX_CPU 2
+#define MAX_IRQ 64
+#define EXT_IRQ 48
+#define MAX_DBL 0
+#define MAX_MBX 0
+#define MAX_TMR 4
+#define VECTOR_BITS 8
+#define MAX_IPI 4
+#define VID 0x03 /* MPIC version ID */
+#define VENI 0x00000000 /* Vendor ID */
+
+enum {
+ IRQ_IPVP = 0,
+ IRQ_IDE,
+};
+
+#define OPENPIC_LITTLE_ENDIAN 1
+#define OPENPIC_BIG_ENDIAN 0
+
+#else
+#error "Please select which OpenPic implementation is to be emulated"
+#endif
+
+#if (OPENPIC_BIG_ENDIAN && !TARGET_WORDS_BIGENDIAN) || \
+ (OPENPIC_LITTLE_ENDIAN && TARGET_WORDS_BIGENDIAN)
+#define OPENPIC_SWAP
+#endif
+
+/* Interrupt definitions */
+#define IRQ_FE (EXT_IRQ) /* Internal functional IRQ */
+#define IRQ_ERR (EXT_IRQ + 1) /* Error IRQ */
+#define IRQ_TIM0 (EXT_IRQ + 2) /* First timer IRQ */
+#if MAX_IPI > 0
+#define IRQ_IPI0 (IRQ_TIM0 + MAX_TMR) /* First IPI IRQ */
+#define IRQ_DBL0 (IRQ_IPI0 + (MAX_CPU * MAX_IPI)) /* First doorbell IRQ */
+#else
+#define IRQ_DBL0 (IRQ_TIM0 + MAX_TMR) /* First doorbell IRQ */
+#define IRQ_MBX0 (IRQ_DBL0 + MAX_DBL) /* First mailbox IRQ */
+#endif
+
+#define BF_WIDTH(_bits_) \
+(((_bits_) + (sizeof(uint32_t) * 8) - 1) / (sizeof(uint32_t) * 8))
+
+static inline void set_bit (uint32_t *field, int bit)
+{
+ field[bit >> 5] |= 1 << (bit & 0x1F);
+}
+
+static inline void reset_bit (uint32_t *field, int bit)
+{
+ field[bit >> 5] &= ~(1 << (bit & 0x1F));
+}
+
+static inline int test_bit (uint32_t *field, int bit)
+{
+ return (field[bit >> 5] & 1 << (bit & 0x1F)) != 0;
+}
+
+enum {
+ IRQ_EXTERNAL = 0x01,
+ IRQ_INTERNAL = 0x02,
+ IRQ_TIMER = 0x04,
+ IRQ_SPECIAL = 0x08,
+} IRQ_src_type;
+
+typedef struct IRQ_queue_t {
+ uint32_t queue[BF_WIDTH(MAX_IRQ)];
+ int next;
+ int priority;
+} IRQ_queue_t;
+
+typedef struct IRQ_src_t {
+ uint32_t ipvp; /* IRQ vector/priority register */
+ uint32_t ide; /* IRQ destination register */
+ int type;
+ int last_cpu;
+ int pending; /* TRUE if IRQ is pending */
+} IRQ_src_t;
+
+enum IPVP_bits {
+ IPVP_MASK = 31,
+ IPVP_ACTIVITY = 30,
+ IPVP_MODE = 29,
+ IPVP_POLARITY = 23,
+ IPVP_SENSE = 22,
+};
+#define IPVP_PRIORITY_MASK (0x1F << 16)
+#define IPVP_PRIORITY(_ipvpr_) ((int)(((_ipvpr_) & IPVP_PRIORITY_MASK) >> 16))
+#define IPVP_VECTOR_MASK ((1 << VECTOR_BITS) - 1)
+#define IPVP_VECTOR(_ipvpr_) ((_ipvpr_) & IPVP_VECTOR_MASK)
+
+typedef struct IRQ_dst_t {
+ uint32_t pctp; /* CPU current task priority */
+ uint32_t pcsr; /* CPU sensitivity register */
+ IRQ_queue_t raised;
+ IRQ_queue_t servicing;
+ CPUState *env; /* Needed if we did SMP */
+} IRQ_dst_t;
+
+struct openpic_t {
+ PCIDevice pci_dev;
+ int mem_index;
+ /* Global registers */
+ uint32_t frep; /* Feature reporting register */
+ uint32_t glbc; /* Global configuration register */
+ uint32_t micr; /* MPIC interrupt configuration register */
+ uint32_t veni; /* Vendor identification register */
+ uint32_t spve; /* Spurious vector register */
+ uint32_t tifr; /* Timer frequency reporting register */
+ /* Source registers */
+ IRQ_src_t src[MAX_IRQ];
+ /* Local registers per output pin */
+ IRQ_dst_t dst[MAX_CPU];
+ int nb_cpus;
+ /* Timer registers */
+ struct {
+ uint32_t ticc; /* Global timer current count register */
+ uint32_t tibc; /* Global timer base count register */
+ } timers[MAX_TMR];
+#if MAX_DBL > 0
+ /* Doorbell registers */
+ uint32_t dar; /* Doorbell activate register */
+ struct {
+ uint32_t dmr; /* Doorbell messaging register */
+ } doorbells[MAX_DBL];
+#endif
+#if MAX_MBX > 0
+ /* Mailbox registers */
+ struct {
+ uint32_t mbr; /* Mailbox register */
+ } mailboxes[MAX_MAILBOXES];
+#endif
+};
+
+static inline void IRQ_setbit (IRQ_queue_t *q, int n_IRQ)
+{
+ set_bit(q->queue, n_IRQ);
+}
+
+static inline void IRQ_resetbit (IRQ_queue_t *q, int n_IRQ)
+{
+ reset_bit(q->queue, n_IRQ);
+}
+
+static inline int IRQ_testbit (IRQ_queue_t *q, int n_IRQ)
+{
+ return test_bit(q->queue, n_IRQ);
+}
+
+static void IRQ_check (openpic_t *opp, IRQ_queue_t *q)
+{
+ int next, i;
+ int priority;
+
+ next = -1;
+ priority = -1;
+ for (i = 0; i < MAX_IRQ; i++) {
+ if (IRQ_testbit(q, i)) {
+ DPRINTF("IRQ_check: irq %d set ipvp_pr=%d pr=%d\n",
+ i, IPVP_PRIORITY(opp->src[i].ipvp), priority);
+ if (IPVP_PRIORITY(opp->src[i].ipvp) > priority) {
+ next = i;
+ priority = IPVP_PRIORITY(opp->src[i].ipvp);
+ }
+ }
+ }
+ q->next = next;
+ q->priority = priority;
+}
+
+static int IRQ_get_next (openpic_t *opp, IRQ_queue_t *q)
+{
+ if (q->next == -1) {
+ /* XXX: optimize */
+ IRQ_check(opp, q);
+ }
+
+ return q->next;
+}
+
+static void IRQ_local_pipe (openpic_t *opp, int n_CPU, int n_IRQ)
+{
+ IRQ_dst_t *dst;
+ IRQ_src_t *src;
+ int priority;
+
+ dst = &opp->dst[n_CPU];
+ src = &opp->src[n_IRQ];
+ priority = IPVP_PRIORITY(src->ipvp);
+ if (priority <= dst->pctp) {
+ /* Too low priority */
+ return;
+ }
+ if (IRQ_testbit(&dst->raised, n_IRQ)) {
+ /* Interrupt miss */
+ return;
+ }
+ set_bit(&src->ipvp, IPVP_ACTIVITY);
+ IRQ_setbit(&dst->raised, n_IRQ);
+ if (priority > dst->raised.priority) {
+ IRQ_get_next(opp, &dst->raised);
+ DPRINTF("Raise CPU IRQ\n");
+ cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HARD);
+ }
+}
+
+/* update pic state because registers for n_IRQ have changed value */
+static void openpic_update_irq(openpic_t *opp, int n_IRQ)
+{
+ IRQ_src_t *src;
+ int i;
+
+ src = &opp->src[n_IRQ];
+
+ if (!src->pending) {
+ /* no irq pending */
+ return;
+ }
+ if (test_bit(&src->ipvp, IPVP_MASK)) {
+ /* Interrupt source is disabled */
+ return;
+ }
+ if (IPVP_PRIORITY(src->ipvp) == 0) {
+ /* Priority set to zero */
+ return;
+ }
+ if (test_bit(&src->ipvp, IPVP_ACTIVITY)) {
+ /* IRQ already active */
+ return;
+ }
+ if (src->ide == 0x00000000) {
+ /* No target */
+ return;
+ }
+
+ if (!test_bit(&src->ipvp, IPVP_MODE) ||
+ src->ide == (1 << src->last_cpu)) {
+ /* Directed delivery mode */
+ for (i = 0; i < opp->nb_cpus; i++) {
+ if (test_bit(&src->ide, i))
+ IRQ_local_pipe(opp, i, n_IRQ);
+ }
+ } else {
+ /* Distributed delivery mode */
+ /* XXX: incorrect code */
+ for (i = src->last_cpu; i < src->last_cpu; i++) {
+ if (i == MAX_IRQ)
+ i = 0;
+ if (test_bit(&src->ide, i)) {
+ IRQ_local_pipe(opp, i, n_IRQ);
+ src->last_cpu = i;
+ break;
+ }
+ }
+ }
+}
+
+void openpic_set_irq(openpic_t *opp, int n_IRQ, int level)
+{
+ IRQ_src_t *src;
+
+ src = &opp->src[n_IRQ];
+ DPRINTF("openpic: set irq %d = %d ipvp=%08x\n",
+ n_IRQ, level, src->ipvp);
+ if (test_bit(&src->ipvp, IPVP_SENSE)) {
+ /* level-sensitive irq */
+ src->pending = level;
+ if (!level)
+ reset_bit(&src->ipvp, IPVP_ACTIVITY);
+ } else {
+ /* edge-sensitive irq */
+ if (level)
+ src->pending = 1;
+ }
+ openpic_update_irq(opp, n_IRQ);
+}
+
+static void openpic_reset (openpic_t *opp)
+{
+ int i;
+
+ opp->glbc = 0x80000000;
+ /* Initialise controler registers */
+ opp->frep = ((EXT_IRQ - 1) << 16) | ((MAX_CPU - 1) << 8) | VID;
+ opp->veni = VENI;
+ opp->spve = 0x000000FF;
+ opp->tifr = 0x003F7A00;
+ /* ? */
+ opp->micr = 0x00000000;
+ /* Initialise IRQ sources */
+ for (i = 0; i < MAX_IRQ; i++) {
+ opp->src[i].ipvp = 0xA0000000;
+ opp->src[i].ide = 0x00000000;
+ }
+ /* Initialise IRQ destinations */
+ for (i = 0; i < opp->nb_cpus; i++) {
+ opp->dst[i].pctp = 0x0000000F;
+ opp->dst[i].pcsr = 0x00000000;
+ memset(&opp->dst[i].raised, 0, sizeof(IRQ_queue_t));
+ memset(&opp->dst[i].servicing, 0, sizeof(IRQ_queue_t));
+ }
+ /* Initialise timers */
+ for (i = 0; i < MAX_TMR; i++) {
+ opp->timers[i].ticc = 0x00000000;
+ opp->timers[i].tibc = 0x80000000;
+ }
+ /* Initialise doorbells */
+#if MAX_DBL > 0
+ opp->dar = 0x00000000;
+ for (i = 0; i < MAX_DBL; i++) {
+ opp->doorbells[i].dmr = 0x00000000;
+ }
+#endif
+ /* Initialise mailboxes */
+#if MAX_MBX > 0
+ for (i = 0; i < MAX_MBX; i++) { /* ? */
+ opp->mailboxes[i].mbr = 0x00000000;
+ }
+#endif
+ /* Go out of RESET state */
+ opp->glbc = 0x00000000;
+}
+
+static inline uint32_t read_IRQreg (openpic_t *opp, int n_IRQ, uint32_t reg)
+{
+ uint32_t retval;
+
+ switch (reg) {
+ case IRQ_IPVP:
+ retval = opp->src[n_IRQ].ipvp;
+ break;
+ case IRQ_IDE:
+ retval = opp->src[n_IRQ].ide;
+ break;
+ }
+
+ return retval;
+}
+
+static inline void write_IRQreg (openpic_t *opp, int n_IRQ,
+ uint32_t reg, uint32_t val)
+{
+ uint32_t tmp;
+
+ switch (reg) {
+ case IRQ_IPVP:
+ /* NOTE: not fully accurate for special IRQs, but simple and
+ sufficient */
+ /* ACTIVITY bit is read-only */
+ opp->src[n_IRQ].ipvp =
+ (opp->src[n_IRQ].ipvp & 0x40000000) |
+ (val & 0x800F00FF);
+ openpic_update_irq(opp, n_IRQ);
+ DPRINTF("Set IPVP %d to 0x%08x -> 0x%08x\n",
+ n_IRQ, val, opp->src[n_IRQ].ipvp);
+ break;
+ case IRQ_IDE:
+ tmp = val & 0xC0000000;
+ tmp |= val & ((1 << MAX_CPU) - 1);
+ opp->src[n_IRQ].ide = tmp;
+ DPRINTF("Set IDE %d to 0x%08x\n", n_IRQ, opp->src[n_IRQ].ide);
+ break;
+ }
+}
+
+#if 0 // Code provision for Intel model
+#if MAX_DBL > 0
+static uint32_t read_doorbell_register (openpic_t *opp,
+ int n_dbl, uint32_t offset)
+{
+ uint32_t retval;
+
+ switch (offset) {
+ case DBL_IPVP_OFFSET:
+ retval = read_IRQreg(opp, IRQ_DBL0 + n_dbl, IRQ_IPVP);
+ break;
+ case DBL_IDE_OFFSET:
+ retval = read_IRQreg(opp, IRQ_DBL0 + n_dbl, IRQ_IDE);
+ break;
+ case DBL_DMR_OFFSET:
+ retval = opp->doorbells[n_dbl].dmr;
+ break;
+ }
+
+ return retval;
+}
+
+static void write_doorbell_register (penpic_t *opp, int n_dbl,
+ uint32_t offset, uint32_t value)
+{
+ switch (offset) {
+ case DBL_IVPR_OFFSET:
+ write_IRQreg(opp, IRQ_DBL0 + n_dbl, IRQ_IPVP, value);
+ break;
+ case DBL_IDE_OFFSET:
+ write_IRQreg(opp, IRQ_DBL0 + n_dbl, IRQ_IDE, value);
+ break;
+ case DBL_DMR_OFFSET:
+ opp->doorbells[n_dbl].dmr = value;
+ break;
+ }
+}
+#endif
+
+#if MAX_MBX > 0
+static uint32_t read_mailbox_register (openpic_t *opp,
+ int n_mbx, uint32_t offset)
+{
+ uint32_t retval;
+
+ switch (offset) {
+ case MBX_MBR_OFFSET:
+ retval = opp->mailboxes[n_mbx].mbr;
+ break;
+ case MBX_IVPR_OFFSET:
+ retval = read_IRQreg(opp, IRQ_MBX0 + n_mbx, IRQ_IPVP);
+ break;
+ case MBX_DMR_OFFSET:
+ retval = read_IRQreg(opp, IRQ_MBX0 + n_mbx, IRQ_IDE);
+ break;
+ }
+
+ return retval;
+}
+
+static void write_mailbox_register (openpic_t *opp, int n_mbx,
+ uint32_t address, uint32_t value)
+{
+ switch (offset) {
+ case MBX_MBR_OFFSET:
+ opp->mailboxes[n_mbx].mbr = value;
+ break;
+ case MBX_IVPR_OFFSET:
+ write_IRQreg(opp, IRQ_MBX0 + n_mbx, IRQ_IPVP, value);
+ break;
+ case MBX_DMR_OFFSET:
+ write_IRQreg(opp, IRQ_MBX0 + n_mbx, IRQ_IDE, value);
+ break;
+ }
+}
+#endif
+#endif /* 0 : Code provision for Intel model */
+
+static void openpic_gbl_write (void *opaque, uint32_t addr, uint32_t val)
+{
+ openpic_t *opp = opaque;
+
+ DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
+ if (addr & 0xF)
+ return;
+#if defined OPENPIC_SWAP
+ val = bswap32(val);
+#endif
+ addr &= 0xFF;
+ switch (addr) {
+ case 0x00: /* FREP */
+ break;
+ case 0x20: /* GLBC */
+ if (val & 0x80000000)
+ openpic_reset(opp);
+ opp->glbc = val & ~0x80000000;
+ break;
+ case 0x80: /* VENI */
+ break;
+ case 0x90: /* PINT */
+ /* XXX: Should be able to reset any CPU */
+ if (val & 1) {
+ DPRINTF("Reset CPU IRQ\n");
+ // cpu_interrupt(cpu_single_env, CPU_INTERRUPT_RESET);
+ }
+ break;
+#if MAX_IPI > 0
+ case 0xA0: /* IPI_IPVP */
+ case 0xB0:
+ case 0xC0:
+ case 0xD0:
+ {
+ int idx;
+ idx = (addr - 0xA0) >> 4;
+ write_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IPVP, val);
+ }
+ break;
+#endif
+ case 0xE0: /* SPVE */
+ opp->spve = val & 0x000000FF;
+ break;
+ case 0xF0: /* TIFR */
+ opp->tifr = val;
+ break;
+ default:
+ break;
+ }
+}
+
+static uint32_t openpic_gbl_read (void *opaque, uint32_t addr)
+{
+ openpic_t *opp = opaque;
+ uint32_t retval;
+
+ DPRINTF("%s: addr %08x\n", __func__, addr);
+ retval = 0xFFFFFFFF;
+ if (addr & 0xF)
+ return retval;
+ addr &= 0xFF;
+ switch (addr) {
+ case 0x00: /* FREP */
+ retval = opp->frep;
+ break;
+ case 0x20: /* GLBC */
+ retval = opp->glbc;
+ break;
+ case 0x80: /* VENI */
+ retval = opp->veni;
+ break;
+ case 0x90: /* PINT */
+ retval = 0x00000000;
+ break;
+#if MAX_IPI > 0
+ case 0xA0: /* IPI_IPVP */
+ case 0xB0:
+ case 0xC0:
+ case 0xD0:
+ {
+ int idx;
+ idx = (addr - 0xA0) >> 4;
+ retval = read_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IPVP);
+ }
+ break;
+#endif
+ case 0xE0: /* SPVE */
+ retval = opp->spve;
+ break;
+ case 0xF0: /* TIFR */
+ retval = opp->tifr;
+ break;
+ default:
+ break;
+ }
+ DPRINTF("%s: => %08x\n", __func__, retval);
+#if defined OPENPIC_SWAP
+ retval = bswap32(retval);
+#endif
+
+ return retval;
+}
+
+static void openpic_timer_write (void *opaque, uint32_t addr, uint32_t val)
+{
+ openpic_t *opp = opaque;
+ int idx;
+
+ DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
+ if (addr & 0xF)
+ return;
+#if defined OPENPIC_SWAP
+ val = bswap32(val);
+#endif
+ addr -= 0x1100;
+ addr &= 0xFFFF;
+ idx = (addr & 0xFFF0) >> 6;
+ addr = addr & 0x30;
+ switch (addr) {
+ case 0x00: /* TICC */
+ break;
+ case 0x10: /* TIBC */
+ if ((opp->timers[idx].ticc & 0x80000000) != 0 &&
+ (val & 0x800000000) == 0 &&
+ (opp->timers[idx].tibc & 0x80000000) != 0)
+ opp->timers[idx].ticc &= ~0x80000000;
+ opp->timers[idx].tibc = val;
+ break;
+ case 0x20: /* TIVP */
+ write_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IPVP, val);
+ break;
+ case 0x30: /* TIDE */
+ write_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IDE, val);
+ break;
+ }
+}
+
+static uint32_t openpic_timer_read (void *opaque, uint32_t addr)
+{
+ openpic_t *opp = opaque;
+ uint32_t retval;
+ int idx;
+
+ DPRINTF("%s: addr %08x\n", __func__, addr);
+ retval = 0xFFFFFFFF;
+ if (addr & 0xF)
+ return retval;
+ addr -= 0x1100;
+ addr &= 0xFFFF;
+ idx = (addr & 0xFFF0) >> 6;
+ addr = addr & 0x30;
+ switch (addr) {
+ case 0x00: /* TICC */
+ retval = opp->timers[idx].ticc;
+ break;
+ case 0x10: /* TIBC */
+ retval = opp->timers[idx].tibc;
+ break;
+ case 0x20: /* TIPV */
+ retval = read_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IPVP);
+ break;
+ case 0x30: /* TIDE */
+ retval = read_IRQreg(opp, IRQ_TIM0 + idx, IRQ_IDE);
+ break;
+ }
+ DPRINTF("%s: => %08x\n", __func__, retval);
+#if defined OPENPIC_SWAP
+ retval = bswap32(retval);
+#endif
+
+ return retval;
+}
+
+static void openpic_src_write (void *opaque, uint32_t addr, uint32_t val)
+{
+ openpic_t *opp = opaque;
+ int idx;
+
+ DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
+ if (addr & 0xF)
+ return;
+#if defined OPENPIC_SWAP
+ val = tswap32(val);
+#endif
+ addr = addr & 0xFFF0;
+ idx = addr >> 5;
+ if (addr & 0x10) {
+ /* EXDE / IFEDE / IEEDE */
+ write_IRQreg(opp, idx, IRQ_IDE, val);
+ } else {
+ /* EXVP / IFEVP / IEEVP */
+ write_IRQreg(opp, idx, IRQ_IPVP, val);
+ }
+}
+
+static uint32_t openpic_src_read (void *opaque, uint32_t addr)
+{
+ openpic_t *opp = opaque;
+ uint32_t retval;
+ int idx;
+
+ DPRINTF("%s: addr %08x\n", __func__, addr);
+ retval = 0xFFFFFFFF;
+ if (addr & 0xF)
+ return retval;
+ addr = addr & 0xFFF0;
+ idx = addr >> 5;
+ if (addr & 0x10) {
+ /* EXDE / IFEDE / IEEDE */
+ retval = read_IRQreg(opp, idx, IRQ_IDE);
+ } else {
+ /* EXVP / IFEVP / IEEVP */
+ retval = read_IRQreg(opp, idx, IRQ_IPVP);
+ }
+ DPRINTF("%s: => %08x\n", __func__, retval);
+#if defined OPENPIC_SWAP
+ retval = tswap32(retval);
+#endif
+
+ return retval;
+}
+
+static void openpic_cpu_write (void *opaque, uint32_t addr, uint32_t val)
+{
+ openpic_t *opp = opaque;
+ IRQ_src_t *src;
+ IRQ_dst_t *dst;
+ int idx, n_IRQ;
+
+ DPRINTF("%s: addr %08x <= %08x\n", __func__, addr, val);
+ if (addr & 0xF)
+ return;
+#if defined OPENPIC_SWAP
+ val = bswap32(val);
+#endif
+ addr &= 0x1FFF0;
+ idx = addr / 0x1000;
+ dst = &opp->dst[idx];
+ addr &= 0xFF0;
+ switch (addr) {
+#if MAX_IPI > 0
+ case 0x40: /* PIPD */
+ case 0x50:
+ case 0x60:
+ case 0x70:
+ idx = (addr - 0x40) >> 4;
+ write_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IDE, val);
+ openpic_set_irq(opp, IRQ_IPI0 + idx, 1);
+ openpic_set_irq(opp, IRQ_IPI0 + idx, 0);
+ break;
+#endif
+ case 0x80: /* PCTP */
+ dst->pctp = val & 0x0000000F;
+ break;
+ case 0x90: /* WHOAMI */
+ /* Read-only register */
+ break;
+ case 0xA0: /* PIAC */
+ /* Read-only register */
+ break;
+ case 0xB0: /* PEOI */
+ DPRINTF("PEOI\n");
+ n_IRQ = IRQ_get_next(opp, &dst->servicing);
+ IRQ_resetbit(&dst->servicing, n_IRQ);
+ dst->servicing.next = -1;
+ src = &opp->src[n_IRQ];
+ /* Set up next servicing IRQ */
+ IRQ_get_next(opp, &dst->servicing);
+ /* Check queued interrupts. */
+ n_IRQ = IRQ_get_next(opp, &dst->raised);
+ if (n_IRQ != -1) {
+ src = &opp->src[n_IRQ];
+ if (IPVP_PRIORITY(src->ipvp) > dst->servicing.priority) {
+ DPRINTF("Raise CPU IRQ\n");
+ cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HARD);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+static uint32_t openpic_cpu_read (void *opaque, uint32_t addr)
+{
+ openpic_t *opp = opaque;
+ IRQ_src_t *src;
+ IRQ_dst_t *dst;
+ uint32_t retval;
+ int idx, n_IRQ;
+
+ DPRINTF("%s: addr %08x\n", __func__, addr);
+ retval = 0xFFFFFFFF;
+ if (addr & 0xF)
+ return retval;
+ addr &= 0x1FFF0;
+ idx = addr / 0x1000;
+ dst = &opp->dst[idx];
+ addr &= 0xFF0;
+ switch (addr) {
+ case 0x80: /* PCTP */
+ retval = dst->pctp;
+ break;
+ case 0x90: /* WHOAMI */
+ retval = idx;
+ break;
+ case 0xA0: /* PIAC */
+ n_IRQ = IRQ_get_next(opp, &dst->raised);
+ DPRINTF("PIAC: irq=%d\n", n_IRQ);
+ if (n_IRQ == -1) {
+ /* No more interrupt pending */
+ retval = opp->spve;
+ } else {
+ src = &opp->src[n_IRQ];
+ if (!test_bit(&src->ipvp, IPVP_ACTIVITY) ||
+ !(IPVP_PRIORITY(src->ipvp) > dst->pctp)) {
+ /* - Spurious level-sensitive IRQ
+ * - Priorities has been changed
+ * and the pending IRQ isn't allowed anymore
+ */
+ reset_bit(&src->ipvp, IPVP_ACTIVITY);
+ retval = IPVP_VECTOR(opp->spve);
+ } else {
+ /* IRQ enter servicing state */
+ IRQ_setbit(&dst->servicing, n_IRQ);
+ retval = IPVP_VECTOR(src->ipvp);
+ }
+ IRQ_resetbit(&dst->raised, n_IRQ);
+ dst->raised.next = -1;
+ if (!test_bit(&src->ipvp, IPVP_SENSE)) {
+ /* edge-sensitive IRQ */
+ reset_bit(&src->ipvp, IPVP_ACTIVITY);
+ src->pending = 0;
+ }
+ }
+ break;
+ case 0xB0: /* PEOI */
+ retval = 0;
+ break;
+#if MAX_IPI > 0
+ case 0x40: /* IDE */
+ case 0x50:
+ idx = (addr - 0x40) >> 4;
+ retval = read_IRQreg(opp, IRQ_IPI0 + idx, IRQ_IDE);
+ break;
+#endif
+ default:
+ break;
+ }
+ DPRINTF("%s: => %08x\n", __func__, retval);
+#if defined OPENPIC_SWAP
+ retval= bswap32(retval);
+#endif
+
+ return retval;
+}
+
+static void openpic_buggy_write (void *opaque,
+ target_phys_addr_t addr, uint32_t val)
+{
+ printf("Invalid OPENPIC write access !\n");
+}
+
+static uint32_t openpic_buggy_read (void *opaque, target_phys_addr_t addr)
+{
+ printf("Invalid OPENPIC read access !\n");
+
+ return -1;
+}
+
+static void openpic_writel (void *opaque,
+ target_phys_addr_t addr, uint32_t val)
+{
+ openpic_t *opp = opaque;
+
+ addr &= 0x3FFFF;
+ DPRINTF("%s: offset %08x val: %08x\n", __func__, (int)addr, val);
+ if (addr < 0x1100) {
+ /* Global registers */
+ openpic_gbl_write(opp, addr, val);
+ } else if (addr < 0x10000) {
+ /* Timers registers */
+ openpic_timer_write(opp, addr, val);
+ } else if (addr < 0x20000) {
+ /* Source registers */
+ openpic_src_write(opp, addr, val);
+ } else {
+ /* CPU registers */
+ openpic_cpu_write(opp, addr, val);
+ }
+}
+
+static uint32_t openpic_readl (void *opaque,target_phys_addr_t addr)
+{
+ openpic_t *opp = opaque;
+ uint32_t retval;
+
+ addr &= 0x3FFFF;
+ DPRINTF("%s: offset %08x\n", __func__, (int)addr);
+ if (addr < 0x1100) {
+ /* Global registers */
+ retval = openpic_gbl_read(opp, addr);
+ } else if (addr < 0x10000) {
+ /* Timers registers */
+ retval = openpic_timer_read(opp, addr);
+ } else if (addr < 0x20000) {
+ /* Source registers */
+ retval = openpic_src_read(opp, addr);
+ } else {
+ /* CPU registers */
+ retval = openpic_cpu_read(opp, addr);
+ }
+
+ return retval;
+}
+
+static CPUWriteMemoryFunc *openpic_write[] = {
+ &openpic_buggy_write,
+ &openpic_buggy_write,
+ &openpic_writel,
+};
+
+static CPUReadMemoryFunc *openpic_read[] = {
+ &openpic_buggy_read,
+ &openpic_buggy_read,
+ &openpic_readl,
+};
+
+static void openpic_map(PCIDevice *pci_dev, int region_num,
+ uint32_t addr, uint32_t size, int type)
+{
+ openpic_t *opp;
+
+ DPRINTF("Map OpenPIC\n");
+ opp = (openpic_t *)pci_dev;
+ /* Global registers */
+ DPRINTF("Register OPENPIC gbl %08x => %08x\n",
+ addr + 0x1000, addr + 0x1000 + 0x100);
+ /* Timer registers */
+ DPRINTF("Register OPENPIC timer %08x => %08x\n",
+ addr + 0x1100, addr + 0x1100 + 0x40 * MAX_TMR);
+ /* Interrupt source registers */
+ DPRINTF("Register OPENPIC src %08x => %08x\n",
+ addr + 0x10000, addr + 0x10000 + 0x20 * (EXT_IRQ + 2));
+ /* Per CPU registers */
+ DPRINTF("Register OPENPIC dst %08x => %08x\n",
+ addr + 0x20000, addr + 0x20000 + 0x1000 * MAX_CPU);
+ cpu_register_physical_memory(addr, 0x40000, opp->mem_index);
+#if 0 // Don't implement ISU for now
+ opp_io_memory = cpu_register_io_memory(0, openpic_src_read,
+ openpic_src_write);
+ cpu_register_physical_memory(isu_base, 0x20 * (EXT_IRQ + 2),
+ opp_io_memory);
+#endif
+}
+
+openpic_t *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus)
+{
+ openpic_t *opp;
+ uint8_t *pci_conf;
+ int i, m;
+
+ /* XXX: for now, only one CPU is supported */
+ if (nb_cpus != 1)
+ return NULL;
+ if (bus) {
+ opp = (openpic_t *)pci_register_device(bus, "OpenPIC", sizeof(openpic_t),
+ -1, NULL, NULL);
+ if (opp == NULL)
+ return NULL;
+ pci_conf = opp->pci_dev.config;
+ pci_conf[0x00] = 0x14; // IBM MPIC2
+ pci_conf[0x01] = 0x10;
+ pci_conf[0x02] = 0xFF;
+ pci_conf[0x03] = 0xFF;
+ pci_conf[0x0a] = 0x80; // PIC
+ pci_conf[0x0b] = 0x08;
+ pci_conf[0x0e] = 0x00; // header_type
+ pci_conf[0x3d] = 0x00; // no interrupt pin
+
+ /* Register I/O spaces */
+ pci_register_io_region((PCIDevice *)opp, 0, 0x40000,
+ PCI_ADDRESS_SPACE_MEM, &openpic_map);
+ } else {
+ opp = qemu_mallocz(sizeof(openpic_t));
+ }
+
+ opp->mem_index = cpu_register_io_memory(0, openpic_read,
+ openpic_write, opp);
+
+ // isu_base &= 0xFFFC0000;
+ opp->nb_cpus = nb_cpus;
+ /* Set IRQ types */
+ for (i = 0; i < EXT_IRQ; i++) {
+ opp->src[i].type = IRQ_EXTERNAL;
+ }
+ for (; i < IRQ_TIM0; i++) {
+ opp->src[i].type = IRQ_SPECIAL;
+ }
+#if MAX_IPI > 0
+ m = IRQ_IPI0;
+#else
+ m = IRQ_DBL0;
+#endif
+ for (; i < m; i++) {
+ opp->src[i].type = IRQ_TIMER;
+ }
+ for (; i < MAX_IRQ; i++) {
+ opp->src[i].type = IRQ_INTERNAL;
+ }
+ openpic_reset(opp);
+ if (pmem_index)
+ *pmem_index = opp->mem_index;
+ return opp;
+}
--- /dev/null
+/*
+ * QEMU PC System Emulator
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+
+/* output Bochs bios info messages */
+//#define DEBUG_BIOS
+
+#define BIOS_FILENAME "bios.bin"
+#define VGABIOS_FILENAME "vgabios.bin"
+#define VGABIOS_CIRRUS_FILENAME "vgabios-cirrus.bin"
+#define LINUX_BOOT_FILENAME "linux_boot.bin"
+
+#define KERNEL_LOAD_ADDR 0x00100000
+#define INITRD_LOAD_ADDR 0x00400000
+#define KERNEL_PARAMS_ADDR 0x00090000
+#define KERNEL_CMDLINE_ADDR 0x00099000
+
+int speaker_data_on;
+int dummy_refresh_clock;
+static fdctrl_t *floppy_controller;
+static RTCState *rtc_state;
+static PITState *pit;
+
+static void ioport80_write(void *opaque, uint32_t addr, uint32_t data)
+{
+}
+
+/* MSDOS compatibility mode FPU exception support */
+/* XXX: add IGNNE support */
+void cpu_set_ferr(CPUX86State *s)
+{
+ pic_set_irq(13, 1);
+}
+
+static void ioportF0_write(void *opaque, uint32_t addr, uint32_t data)
+{
+ pic_set_irq(13, 0);
+}
+
+/* TSC handling */
+
+uint64_t cpu_get_tsc(CPUX86State *env)
+{
+ return qemu_get_clock(vm_clock);
+}
+
+/* PC cmos mappings */
+
+#define REG_EQUIPMENT_BYTE 0x14
+#define REG_IBM_CENTURY_BYTE 0x32
+#define REG_IBM_PS2_CENTURY_BYTE 0x37
+
+
+static inline int to_bcd(RTCState *s, int a)
+{
+ return ((a / 10) << 4) | (a % 10);
+}
+
+static int cmos_get_fd_drive_type(int fd0)
+{
+ int val;
+
+ switch (fd0) {
+ case 0:
+ /* 1.44 Mb 3"5 drive */
+ val = 4;
+ break;
+ case 1:
+ /* 2.88 Mb 3"5 drive */
+ val = 5;
+ break;
+ case 2:
+ /* 1.2 Mb 5"5 drive */
+ val = 2;
+ break;
+ default:
+ val = 0;
+ break;
+ }
+ return val;
+}
+
+static void cmos_init_hd(int type_ofs, int info_ofs, BlockDriverState *hd)
+{
+ RTCState *s = rtc_state;
+ int cylinders, heads, sectors;
+ bdrv_get_geometry_hint(hd, &cylinders, &heads, §ors);
+ rtc_set_memory(s, type_ofs, 47);
+ rtc_set_memory(s, info_ofs, cylinders);
+ rtc_set_memory(s, info_ofs + 1, cylinders >> 8);
+ rtc_set_memory(s, info_ofs + 2, heads);
+ rtc_set_memory(s, info_ofs + 3, 0xff);
+ rtc_set_memory(s, info_ofs + 4, 0xff);
+ rtc_set_memory(s, info_ofs + 5, 0xc0 | ((heads > 8) << 3));
+ rtc_set_memory(s, info_ofs + 6, cylinders);
+ rtc_set_memory(s, info_ofs + 7, cylinders >> 8);
+ rtc_set_memory(s, info_ofs + 8, sectors);
+}
+
+/* hd_table must contain 4 block drivers */
+static void cmos_init(int ram_size, int boot_device, BlockDriverState **hd_table)
+{
+ RTCState *s = rtc_state;
+ int val;
+ int fd0, fd1, nb;
+ time_t ti;
+ struct tm *tm;
+ int i;
+
+ /* set the CMOS date */
+ time(&ti);
+ if (rtc_utc)
+ tm = gmtime(&ti);
+ else
+ tm = localtime(&ti);
+ rtc_set_date(s, tm);
+
+ val = to_bcd(s, (tm->tm_year / 100) + 19);
+ rtc_set_memory(s, REG_IBM_CENTURY_BYTE, val);
+ rtc_set_memory(s, REG_IBM_PS2_CENTURY_BYTE, val);
+
+ /* various important CMOS locations needed by PC/Bochs bios */
+
+ /* memory size */
+ val = 640; /* base memory in K */
+ rtc_set_memory(s, 0x15, val);
+ rtc_set_memory(s, 0x16, val >> 8);
+
+ val = (ram_size / 1024) - 1024;
+ if (val > 65535)
+ val = 65535;
+ rtc_set_memory(s, 0x17, val);
+ rtc_set_memory(s, 0x18, val >> 8);
+ rtc_set_memory(s, 0x30, val);
+ rtc_set_memory(s, 0x31, val >> 8);
+
+ if (ram_size > (16 * 1024 * 1024))
+ val = (ram_size / 65536) - ((16 * 1024 * 1024) / 65536);
+ else
+ val = 0;
+ if (val > 65535)
+ val = 65535;
+ rtc_set_memory(s, 0x34, val);
+ rtc_set_memory(s, 0x35, val >> 8);
+
+ switch(boot_device) {
+ case 'a':
+ case 'b':
+ rtc_set_memory(s, 0x3d, 0x01); /* floppy boot */
+ break;
+ default:
+ case 'c':
+ rtc_set_memory(s, 0x3d, 0x02); /* hard drive boot */
+ break;
+ case 'd':
+ rtc_set_memory(s, 0x3d, 0x03); /* CD-ROM boot */
+ break;
+ }
+
+ /* floppy type */
+
+ fd0 = fdctrl_get_drive_type(floppy_controller, 0);
+ fd1 = fdctrl_get_drive_type(floppy_controller, 1);
+
+ val = (cmos_get_fd_drive_type(fd0) << 4) | cmos_get_fd_drive_type(fd1);
+ rtc_set_memory(s, 0x10, val);
+
+ val = 0;
+ nb = 0;
+ if (fd0 < 3)
+ nb++;
+ if (fd1 < 3)
+ nb++;
+ switch (nb) {
+ case 0:
+ break;
+ case 1:
+ val |= 0x01; /* 1 drive, ready for boot */
+ break;
+ case 2:
+ val |= 0x41; /* 2 drives, ready for boot */
+ break;
+ }
+ val |= 0x02; /* FPU is there */
+ val |= 0x04; /* PS/2 mouse installed */
+ rtc_set_memory(s, REG_EQUIPMENT_BYTE, val);
+
+ /* hard drives */
+
+ rtc_set_memory(s, 0x12, (hd_table[0] ? 0xf0 : 0) | (hd_table[1] ? 0x0f : 0));
+ if (hd_table[0])
+ cmos_init_hd(0x19, 0x1b, hd_table[0]);
+ if (hd_table[1])
+ cmos_init_hd(0x1a, 0x24, hd_table[1]);
+
+ val = 0;
+ for (i = 0; i < 4; i++) {
+ if (hd_table[i]) {
+ int cylinders, heads, sectors;
+ uint8_t translation;
+ /* NOTE: bdrv_get_geometry_hint() returns the geometry
+ that the hard disk returns. It is always such that: 1 <=
+ sects <= 63, 1 <= heads <= 16, 1 <= cylinders <=
+ 16383. The BIOS geometry can be different. */
+ bdrv_get_geometry_hint(hd_table[i], &cylinders, &heads, §ors);
+ if (cylinders <= 1024 && heads <= 16 && sectors <= 63) {
+ /* No translation. */
+ translation = 0;
+ } else {
+ /* LBA translation. */
+ translation = 1;
+ }
+ val |= translation << (i * 2);
+ }
+ }
+ rtc_set_memory(s, 0x39, val);
+
+ /* Disable check of 0x55AA signature on the last two bytes of
+ first sector of disk. XXX: make it the default ? */
+ // rtc_set_memory(s, 0x38, 1);
+}
+
+static void speaker_ioport_write(void *opaque, uint32_t addr, uint32_t val)
+{
+ speaker_data_on = (val >> 1) & 1;
+ pit_set_gate(pit, 2, val & 1);
+}
+
+static uint32_t speaker_ioport_read(void *opaque, uint32_t addr)
+{
+ int out;
+ out = pit_get_out(pit, 2, qemu_get_clock(vm_clock));
+ dummy_refresh_clock ^= 1;
+ return (speaker_data_on << 1) | pit_get_gate(pit, 2) | (out << 5) |
+ (dummy_refresh_clock << 4);
+}
+
+static void ioport92_write(void *opaque, uint32_t addr, uint32_t val)
+{
+ cpu_x86_set_a20(cpu_single_env, (val >> 1) & 1);
+ /* XXX: bit 0 is fast reset */
+}
+
+static uint32_t ioport92_read(void *opaque, uint32_t addr)
+{
+ return ((cpu_single_env->a20_mask >> 20) & 1) << 1;
+}
+
+/***********************************************************/
+/* Bochs BIOS debug ports */
+
+void bochs_bios_write(void *opaque, uint32_t addr, uint32_t val)
+{
+ static const char shutdown_str[8] = "Shutdown";
+ static int shutdown_index = 0;
+
+ switch(addr) {
+ /* Bochs BIOS messages */
+ case 0x400:
+ case 0x401:
+ fprintf(stderr, "BIOS panic at rombios.c, line %d\n", val);
+ exit(1);
+ case 0x402:
+ case 0x403:
+#ifdef DEBUG_BIOS
+ fprintf(stderr, "%c", val);
+#endif
+ break;
+ case 0x8900:
+ /* same as Bochs power off */
+ if (val == shutdown_str[shutdown_index]) {
+ shutdown_index++;
+ if (shutdown_index == 8) {
+ shutdown_index = 0;
+ qemu_system_shutdown_request();
+ }
+ } else {
+ shutdown_index = 0;
+ }
+ break;
+
+ /* LGPL'ed VGA BIOS messages */
+ case 0x501:
+ case 0x502:
+ fprintf(stderr, "VGA BIOS panic, line %d\n", val);
+ exit(1);
+ case 0x500:
+ case 0x503:
+#ifdef DEBUG_BIOS
+ fprintf(stderr, "%c", val);
+#endif
+ break;
+ }
+}
+
+void bochs_bios_init(void)
+{
+ register_ioport_write(0x400, 1, 2, bochs_bios_write, NULL);
+ register_ioport_write(0x401, 1, 2, bochs_bios_write, NULL);
+ register_ioport_write(0x402, 1, 1, bochs_bios_write, NULL);
+ register_ioport_write(0x403, 1, 1, bochs_bios_write, NULL);
+ register_ioport_write(0x8900, 1, 1, bochs_bios_write, NULL);
+
+ register_ioport_write(0x501, 1, 2, bochs_bios_write, NULL);
+ register_ioport_write(0x502, 1, 2, bochs_bios_write, NULL);
+ register_ioport_write(0x500, 1, 1, bochs_bios_write, NULL);
+ register_ioport_write(0x503, 1, 1, bochs_bios_write, NULL);
+}
+
+
+int load_kernel(const char *filename, uint8_t *addr,
+ uint8_t *real_addr)
+{
+ int fd, size;
+ int setup_sects;
+
+ fd = open(filename, O_RDONLY | O_BINARY);
+ if (fd < 0)
+ return -1;
+
+ /* load 16 bit code */
+ if (read(fd, real_addr, 512) != 512)
+ goto fail;
+ setup_sects = real_addr[0x1F1];
+ if (!setup_sects)
+ setup_sects = 4;
+ if (read(fd, real_addr + 512, setup_sects * 512) !=
+ setup_sects * 512)
+ goto fail;
+
+ /* load 32 bit code */
+ size = read(fd, addr, 16 * 1024 * 1024);
+ if (size < 0)
+ goto fail;
+ close(fd);
+ return size;
+ fail:
+ close(fd);
+ return -1;
+}
+
+static const int ide_iobase[2] = { 0x1f0, 0x170 };
+static const int ide_iobase2[2] = { 0x3f6, 0x376 };
+static const int ide_irq[2] = { 14, 15 };
+
+#define NE2000_NB_MAX 6
+
+static int ne2000_io[NE2000_NB_MAX] = { 0x300, 0x320, 0x340, 0x360, 0x280, 0x380 };
+static int ne2000_irq[NE2000_NB_MAX] = { 9, 10, 11, 3, 4, 5 };
+
+static int serial_io[MAX_SERIAL_PORTS] = { 0x3f8, 0x2f8, 0x3e8, 0x2e8 };
+static int serial_irq[MAX_SERIAL_PORTS] = { 4, 3, 4, 3 };
+
+#define NOBIOS 1
+
+/* PC hardware initialisation */
+void pc_init(int ram_size, int vga_ram_size, int boot_device,
+ DisplayState *ds, const char **fd_filename, int snapshot,
+ const char *kernel_filename, const char *kernel_cmdline,
+ const char *initrd_filename)
+{
+ char buf[1024];
+ int ret, linux_boot, initrd_size, i, nb_nics1;
+ unsigned long bios_offset, vga_bios_offset;
+ int bios_size, isa_bios_size;
+ PCIBus *pci_bus;
+
+ linux_boot = (kernel_filename != NULL);
+
+ /* allocate RAM */
+// cpu_register_physical_memory(0, ram_size, 0);
+
+#ifndef NOBIOS
+ /* BIOS load */
+ bios_offset = ram_size + vga_ram_size;
+ vga_bios_offset = bios_offset + 256 * 1024;
+
+ snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
+ bios_size = get_image_size(buf);
+ if (bios_size <= 0 ||
+ (bios_size % 65536) != 0 ||
+ bios_size > (256 * 1024)) {
+ goto bios_error;
+ }
+ ret = load_image(buf, phys_ram_base + bios_offset);
+ if (ret != bios_size) {
+ bios_error:
+ fprintf(stderr, "qemu: could not load PC bios '%s'\n", buf);
+ exit(1);
+ }
+
+ /* VGA BIOS load */
+ if (cirrus_vga_enabled) {
+ snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_CIRRUS_FILENAME);
+ } else {
+ snprintf(buf, sizeof(buf), "%s/%s", bios_dir, VGABIOS_FILENAME);
+ }
+ ret = load_image(buf, phys_ram_base + vga_bios_offset);
+#endif
+
+ /* setup basic memory access */
+ cpu_register_physical_memory(0xc0000, 0x10000,
+ vga_bios_offset | IO_MEM_ROM);
+
+#ifndef NOBIOS
+ /* map the last 128KB of the BIOS in ISA space */
+ isa_bios_size = bios_size;
+ if (isa_bios_size > (128 * 1024))
+ isa_bios_size = 128 * 1024;
+ cpu_register_physical_memory(0xd0000, (192 * 1024) - isa_bios_size,
+ IO_MEM_UNASSIGNED);
+ cpu_register_physical_memory(0x100000 - isa_bios_size,
+ isa_bios_size,
+ (bios_offset + bios_size - isa_bios_size) | IO_MEM_ROM);
+ /* map all the bios at the top of memory */
+ cpu_register_physical_memory((uint32_t)(-bios_size),
+ bios_size, bios_offset | IO_MEM_ROM);
+
+ bochs_bios_init();
+#endif
+
+ if (linux_boot) {
+ uint8_t bootsect[512];
+ uint8_t old_bootsect[512];
+
+ if (bs_table[0] == NULL) {
+ fprintf(stderr, "A disk image must be given for 'hda' when booting a Linux kernel\n");
+ exit(1);
+ }
+ snprintf(buf, sizeof(buf), "%s/%s", bios_dir, LINUX_BOOT_FILENAME);
+ ret = load_image(buf, bootsect);
+ if (ret != sizeof(bootsect)) {
+ fprintf(stderr, "qemu: could not load linux boot sector '%s'\n",
+ buf);
+ exit(1);
+ }
+
+ if (bdrv_read(bs_table[0], 0, old_bootsect, 1) >= 0) {
+ /* copy the MSDOS partition table */
+ memcpy(bootsect + 0x1be, old_bootsect + 0x1be, 0x40);
+ }
+
+ bdrv_set_boot_sector(bs_table[0], bootsect, sizeof(bootsect));
+
+ /* now we can load the kernel */
+ ret = load_kernel(kernel_filename,
+ phys_ram_base + KERNEL_LOAD_ADDR,
+ phys_ram_base + KERNEL_PARAMS_ADDR);
+ if (ret < 0) {
+ fprintf(stderr, "qemu: could not load kernel '%s'\n",
+ kernel_filename);
+ exit(1);
+ }
+
+ /* load initrd */
+ initrd_size = 0;
+ if (initrd_filename) {
+ initrd_size = load_image(initrd_filename, phys_ram_base + INITRD_LOAD_ADDR);
+ if (initrd_size < 0) {
+ fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
+ initrd_filename);
+ exit(1);
+ }
+ }
+ if (initrd_size > 0) {
+ stl_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x218, INITRD_LOAD_ADDR);
+ stl_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x21c, initrd_size);
+ }
+ pstrcpy(phys_ram_base + KERNEL_CMDLINE_ADDR, 4096,
+ kernel_cmdline);
+ stw_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x20, 0xA33F);
+ stw_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x22,
+ KERNEL_CMDLINE_ADDR - KERNEL_PARAMS_ADDR);
+ /* loader type */
+ stw_raw(phys_ram_base + KERNEL_PARAMS_ADDR + 0x210, 0x01);
+ }
+
+ if (pci_enabled) {
+ pci_bus = i440fx_init();
+ piix3_init(pci_bus);
+ } else {
+ pci_bus = NULL;
+ }
+
+ /* init basic PC hardware */
+ register_ioport_write(0x80, 1, 1, ioport80_write, NULL);
+
+ register_ioport_write(0xf0, 1, 1, ioportF0_write, NULL);
+
+#ifdef NOBIOS
+ cirrus_vga_enabled = 0;
+#endif
+ if (cirrus_vga_enabled) {
+ if (pci_enabled) {
+ pci_cirrus_vga_init(pci_bus,
+ ds, phys_ram_base + ram_size, ram_size,
+ vga_ram_size);
+ } else {
+ isa_cirrus_vga_init(ds, phys_ram_base + ram_size, ram_size,
+ vga_ram_size);
+ }
+ } else {
+ vga_initialize(pci_bus, ds, phys_ram_base + ram_size, ram_size,
+ vga_ram_size);
+ }
+
+ rtc_state = rtc_init(0x70, 8);
+ register_ioport_read(0x61, 1, 1, speaker_ioport_read, NULL);
+ register_ioport_write(0x61, 1, 1, speaker_ioport_write, NULL);
+
+ register_ioport_read(0x92, 1, 1, ioport92_read, NULL);
+ register_ioport_write(0x92, 1, 1, ioport92_write, NULL);
+
+ pic_init();
+ pit = pit_init(0x40, 0);
+
+ for(i = 0; i < MAX_SERIAL_PORTS; i++) {
+ if (serial_hds[i]) {
+ serial_init(serial_io[i], serial_irq[i], serial_hds[i]);
+ }
+ }
+
+ if (pci_enabled) {
+ for(i = 0; i < nb_nics; i++) {
+ pci_ne2000_init(pci_bus, &nd_table[i]);
+ }
+ pci_piix3_ide_init(pci_bus, bs_table);
+ } else {
+ nb_nics1 = nb_nics;
+ if (nb_nics1 > NE2000_NB_MAX)
+ nb_nics1 = NE2000_NB_MAX;
+ for(i = 0; i < nb_nics1; i++) {
+ isa_ne2000_init(ne2000_io[i], ne2000_irq[i], &nd_table[i]);
+ }
+
+ for(i = 0; i < 2; i++) {
+ isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i],
+ bs_table[2 * i], bs_table[2 * i + 1]);
+ }
+ }
+
+ kbd_init();
+ DMA_init(0);
+
+ floppy_controller = fdctrl_init(6, 2, 0, 0x3f0, fd_table);
+
+ cmos_init(ram_size, boot_device, bs_table);
+
+ /* must be done after all PCI devices are instanciated */
+ /* XXX: should be done in the Bochs BIOS */
+ if (pci_enabled) {
+ pci_bios_init();
+ }
+}
--- /dev/null
+/*
+ * QEMU PCI bus manager
+ *
+ * Copyright (c) 2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+
+//#define DEBUG_PCI
+
+#define PCI_VENDOR_ID 0x00 /* 16 bits */
+#define PCI_DEVICE_ID 0x02 /* 16 bits */
+#define PCI_COMMAND 0x04 /* 16 bits */
+#define PCI_COMMAND_IO 0x1 /* Enable response in I/O space */
+#define PCI_COMMAND_MEMORY 0x2 /* Enable response in Memory space */
+#define PCI_CLASS_DEVICE 0x0a /* Device class */
+#define PCI_INTERRUPT_LINE 0x3c /* 8 bits */
+#define PCI_INTERRUPT_PIN 0x3d /* 8 bits */
+#define PCI_MIN_GNT 0x3e /* 8 bits */
+#define PCI_MAX_LAT 0x3f /* 8 bits */
+
+/* just used for simpler irq handling. */
+#define PCI_DEVICES_MAX 64
+#define PCI_IRQ_WORDS ((PCI_DEVICES_MAX + 31) / 32)
+
+struct PCIBus {
+ int bus_num;
+ int devfn_min;
+ void (*set_irq)(PCIDevice *pci_dev, int irq_num, int level);
+ uint32_t config_reg; /* XXX: suppress */
+ openpic_t *openpic; /* XXX: suppress */
+ PCIDevice *devices[256];
+};
+
+target_phys_addr_t pci_mem_base;
+static int pci_irq_index;
+static uint32_t pci_irq_levels[4][PCI_IRQ_WORDS];
+static PCIBus *first_bus;
+
+static PCIBus *pci_register_bus(void)
+{
+ PCIBus *bus;
+ bus = qemu_mallocz(sizeof(PCIBus));
+ first_bus = bus;
+ return bus;
+}
+
+void generic_pci_save(QEMUFile* f, void *opaque)
+{
+ PCIDevice* s=(PCIDevice*)opaque;
+
+ qemu_put_buffer(f, s->config, 256);
+}
+
+int generic_pci_load(QEMUFile* f, void *opaque, int version_id)
+{
+ PCIDevice* s=(PCIDevice*)opaque;
+
+ if (version_id != 1)
+ return -EINVAL;
+
+ qemu_get_buffer(f, s->config, 256);
+ return 0;
+}
+
+/* -1 for devfn means auto assign */
+PCIDevice *pci_register_device(PCIBus *bus, const char *name,
+ int instance_size, int devfn,
+ PCIConfigReadFunc *config_read,
+ PCIConfigWriteFunc *config_write)
+{
+ PCIDevice *pci_dev;
+
+ if (pci_irq_index >= PCI_DEVICES_MAX)
+ return NULL;
+
+ if (devfn < 0) {
+ for(devfn = bus->devfn_min ; devfn < 256; devfn += 8) {
+ if (!bus->devices[devfn])
+ goto found;
+ }
+ return NULL;
+ found: ;
+ }
+ pci_dev = qemu_mallocz(instance_size);
+ if (!pci_dev)
+ return NULL;
+ pci_dev->bus = bus;
+ pci_dev->devfn = devfn;
+ pstrcpy(pci_dev->name, sizeof(pci_dev->name), name);
+
+ if (!config_read)
+ config_read = pci_default_read_config;
+ if (!config_write)
+ config_write = pci_default_write_config;
+ pci_dev->config_read = config_read;
+ pci_dev->config_write = config_write;
+ pci_dev->irq_index = pci_irq_index++;
+ bus->devices[devfn] = pci_dev;
+ return pci_dev;
+}
+
+void pci_register_io_region(PCIDevice *pci_dev, int region_num,
+ uint32_t size, int type,
+ PCIMapIORegionFunc *map_func)
+{
+ PCIIORegion *r;
+
+ if ((unsigned int)region_num >= PCI_NUM_REGIONS)
+ return;
+ r = &pci_dev->io_regions[region_num];
+ r->addr = -1;
+ r->size = size;
+ r->type = type;
+ r->map_func = map_func;
+}
+
+static void pci_addr_writel(void* opaque, uint32_t addr, uint32_t val)
+{
+ PCIBus *s = opaque;
+ s->config_reg = val;
+}
+
+static uint32_t pci_addr_readl(void* opaque, uint32_t addr)
+{
+ PCIBus *s = opaque;
+ return s->config_reg;
+}
+
+static void pci_update_mappings(PCIDevice *d)
+{
+ PCIIORegion *r;
+ int cmd, i;
+ uint32_t last_addr, new_addr, config_ofs;
+
+ cmd = le16_to_cpu(*(uint16_t *)(d->config + PCI_COMMAND));
+ for(i = 0; i < PCI_NUM_REGIONS; i++) {
+ r = &d->io_regions[i];
+ if (i == PCI_ROM_SLOT) {
+ config_ofs = 0x30;
+ } else {
+ config_ofs = 0x10 + i * 4;
+ }
+ if (r->size != 0) {
+ if (r->type & PCI_ADDRESS_SPACE_IO) {
+ if (cmd & PCI_COMMAND_IO) {
+ new_addr = le32_to_cpu(*(uint32_t *)(d->config +
+ config_ofs));
+ new_addr = new_addr & ~(r->size - 1);
+ last_addr = new_addr + r->size - 1;
+ /* NOTE: we have only 64K ioports on PC */
+ if (last_addr <= new_addr || new_addr == 0 ||
+ last_addr >= 0x10000) {
+ new_addr = -1;
+ }
+ } else {
+ new_addr = -1;
+ }
+ } else {
+ if (cmd & PCI_COMMAND_MEMORY) {
+ new_addr = le32_to_cpu(*(uint32_t *)(d->config +
+ config_ofs));
+ /* the ROM slot has a specific enable bit */
+ if (i == PCI_ROM_SLOT && !(new_addr & 1))
+ goto no_mem_map;
+ new_addr = new_addr & ~(r->size - 1);
+ last_addr = new_addr + r->size - 1;
+ /* NOTE: we do not support wrapping */
+ /* XXX: as we cannot support really dynamic
+ mappings, we handle specific values as invalid
+ mappings. */
+ if (last_addr <= new_addr || new_addr == 0 ||
+ last_addr == -1) {
+ new_addr = -1;
+ }
+ } else {
+ no_mem_map:
+ new_addr = -1;
+ }
+ }
+ /* now do the real mapping */
+ if (new_addr != r->addr) {
+ if (r->addr != -1) {
+ if (r->type & PCI_ADDRESS_SPACE_IO) {
+ int class;
+ /* NOTE: specific hack for IDE in PC case:
+ only one byte must be mapped. */
+ class = d->config[0x0a] | (d->config[0x0b] << 8);
+ if (class == 0x0101 && r->size == 4) {
+ isa_unassign_ioport(r->addr + 2, 1);
+ } else {
+ isa_unassign_ioport(r->addr, r->size);
+ }
+ } else {
+ cpu_register_physical_memory(r->addr + pci_mem_base,
+ r->size,
+ IO_MEM_UNASSIGNED);
+ }
+ }
+ r->addr = new_addr;
+ if (r->addr != -1) {
+ r->map_func(d, i, r->addr, r->size, r->type);
+ }
+ }
+ }
+ }
+}
+
+uint32_t pci_default_read_config(PCIDevice *d,
+ uint32_t address, int len)
+{
+ uint32_t val;
+ switch(len) {
+ case 1:
+ val = d->config[address];
+ break;
+ case 2:
+ val = le16_to_cpu(*(uint16_t *)(d->config + address));
+ break;
+ default:
+ case 4:
+ val = le32_to_cpu(*(uint32_t *)(d->config + address));
+ break;
+ }
+ return val;
+}
+
+void pci_default_write_config(PCIDevice *d,
+ uint32_t address, uint32_t val, int len)
+{
+ int can_write, i;
+ uint32_t end, addr;
+
+ if (len == 4 && ((address >= 0x10 && address < 0x10 + 4 * 6) ||
+ (address >= 0x30 && address < 0x34))) {
+ PCIIORegion *r;
+ int reg;
+
+ if ( address >= 0x30 ) {
+ reg = PCI_ROM_SLOT;
+ }else{
+ reg = (address - 0x10) >> 2;
+ }
+ r = &d->io_regions[reg];
+ if (r->size == 0)
+ goto default_config;
+ /* compute the stored value */
+ if (reg == PCI_ROM_SLOT) {
+ /* keep ROM enable bit */
+ val &= (~(r->size - 1)) | 1;
+ } else {
+ val &= ~(r->size - 1);
+ val |= r->type;
+ }
+ *(uint32_t *)(d->config + address) = cpu_to_le32(val);
+ pci_update_mappings(d);
+ return;
+ }
+ default_config:
+ /* not efficient, but simple */
+ addr = address;
+ for(i = 0; i < len; i++) {
+ /* default read/write accesses */
+ switch(d->config[0x0e]) {
+ case 0x00:
+ case 0x80:
+ switch(addr) {
+ case 0x00:
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ case 0x08:
+ case 0x09:
+ case 0x0a:
+ case 0x0b:
+ case 0x0e:
+ case 0x10 ... 0x27: /* base */
+ case 0x30 ... 0x33: /* rom */
+ case 0x3d:
+ can_write = 0;
+ break;
+ default:
+ can_write = 1;
+ break;
+ }
+ break;
+ default:
+ case 0x01:
+ switch(addr) {
+ case 0x00:
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ case 0x08:
+ case 0x09:
+ case 0x0a:
+ case 0x0b:
+ case 0x0e:
+ case 0x38 ... 0x3b: /* rom */
+ case 0x3d:
+ can_write = 0;
+ break;
+ default:
+ can_write = 1;
+ break;
+ }
+ break;
+ }
+ if (can_write) {
+ d->config[addr] = val;
+ }
+ addr++;
+ val >>= 8;
+ }
+
+ end = address + len;
+ if (end > PCI_COMMAND && address < (PCI_COMMAND + 2)) {
+ /* if the command register is modified, we must modify the mappings */
+ pci_update_mappings(d);
+ }
+}
+
+static void pci_data_write(void *opaque, uint32_t addr,
+ uint32_t val, int len)
+{
+ PCIBus *s = opaque;
+ PCIDevice *pci_dev;
+ int config_addr, bus_num;
+
+#if defined(DEBUG_PCI) && 0
+ printf("pci_data_write: addr=%08x val=%08x len=%d\n",
+ s->config_reg, val, len);
+#endif
+ if (!(s->config_reg & (1 << 31))) {
+ return;
+ }
+ if ((s->config_reg & 0x3) != 0) {
+ return;
+ }
+ bus_num = (s->config_reg >> 16) & 0xff;
+ if (bus_num != 0)
+ return;
+ pci_dev = s->devices[(s->config_reg >> 8) & 0xff];
+ if (!pci_dev)
+ return;
+ config_addr = (s->config_reg & 0xfc) | (addr & 3);
+#if defined(DEBUG_PCI)
+ printf("pci_config_write: %s: addr=%02x val=%08x len=%d\n",
+ pci_dev->name, config_addr, val, len);
+#endif
+ pci_dev->config_write(pci_dev, config_addr, val, len);
+}
+
+static uint32_t pci_data_read(void *opaque, uint32_t addr,
+ int len)
+{
+ PCIBus *s = opaque;
+ PCIDevice *pci_dev;
+ int config_addr, bus_num;
+ uint32_t val;
+
+ if (!(s->config_reg & (1 << 31)))
+ goto fail;
+ if ((s->config_reg & 0x3) != 0)
+ goto fail;
+ bus_num = (s->config_reg >> 16) & 0xff;
+ if (bus_num != 0)
+ goto fail;
+ pci_dev = s->devices[(s->config_reg >> 8) & 0xff];
+ if (!pci_dev) {
+ fail:
+ switch(len) {
+ case 1:
+ val = 0xff;
+ break;
+ case 2:
+ val = 0xffff;
+ break;
+ default:
+ case 4:
+ val = 0xffffffff;
+ break;
+ }
+ goto the_end;
+ }
+ config_addr = (s->config_reg & 0xfc) | (addr & 3);
+ val = pci_dev->config_read(pci_dev, config_addr, len);
+#if defined(DEBUG_PCI)
+ printf("pci_config_read: %s: addr=%02x val=%08x len=%d\n",
+ pci_dev->name, config_addr, val, len);
+#endif
+ the_end:
+#if defined(DEBUG_PCI) && 0
+ printf("pci_data_read: addr=%08x val=%08x len=%d\n",
+ s->config_reg, val, len);
+#endif
+ return val;
+}
+
+static void pci_data_writeb(void* opaque, uint32_t addr, uint32_t val)
+{
+ pci_data_write(opaque, addr, val, 1);
+}
+
+static void pci_data_writew(void* opaque, uint32_t addr, uint32_t val)
+{
+ pci_data_write(opaque, addr, val, 2);
+}
+
+static void pci_data_writel(void* opaque, uint32_t addr, uint32_t val)
+{
+ pci_data_write(opaque, addr, val, 4);
+}
+
+static uint32_t pci_data_readb(void* opaque, uint32_t addr)
+{
+ return pci_data_read(opaque, addr, 1);
+}
+
+static uint32_t pci_data_readw(void* opaque, uint32_t addr)
+{
+ return pci_data_read(opaque, addr, 2);
+}
+
+static uint32_t pci_data_readl(void* opaque, uint32_t addr)
+{
+ return pci_data_read(opaque, addr, 4);
+}
+
+/* i440FX PCI bridge */
+
+static void piix3_set_irq(PCIDevice *pci_dev, int irq_num, int level);
+
+PCIBus *i440fx_init(void)
+{
+ PCIBus *s;
+ PCIDevice *d;
+
+ s = pci_register_bus();
+ s->set_irq = piix3_set_irq;
+
+ register_ioport_write(0xcf8, 4, 4, pci_addr_writel, s);
+ register_ioport_read(0xcf8, 4, 4, pci_addr_readl, s);
+
+ register_ioport_write(0xcfc, 4, 1, pci_data_writeb, s);
+ register_ioport_write(0xcfc, 4, 2, pci_data_writew, s);
+ register_ioport_write(0xcfc, 4, 4, pci_data_writel, s);
+ register_ioport_read(0xcfc, 4, 1, pci_data_readb, s);
+ register_ioport_read(0xcfc, 4, 2, pci_data_readw, s);
+ register_ioport_read(0xcfc, 4, 4, pci_data_readl, s);
+
+ d = pci_register_device(s, "i440FX", sizeof(PCIDevice), 0,
+ NULL, NULL);
+
+ d->config[0x00] = 0x86; // vendor_id
+ d->config[0x01] = 0x80;
+ d->config[0x02] = 0x37; // device_id
+ d->config[0x03] = 0x12;
+ d->config[0x08] = 0x02; // revision
+ d->config[0x0a] = 0x00; // class_sub = host2pci
+ d->config[0x0b] = 0x06; // class_base = PCI_bridge
+ d->config[0x0e] = 0x00; // header_type
+ return s;
+}
+
+/* PIIX3 PCI to ISA bridge */
+
+typedef struct PIIX3State {
+ PCIDevice dev;
+} PIIX3State;
+
+PIIX3State *piix3_state;
+
+/* return the global irq number corresponding to a given device irq
+ pin. We could also use the bus number to have a more precise
+ mapping. */
+static inline int pci_slot_get_pirq(PCIDevice *pci_dev, int irq_num)
+{
+ int slot_addend;
+ slot_addend = (pci_dev->devfn >> 3);
+ return (irq_num + slot_addend) & 3;
+}
+
+static void piix3_set_irq(PCIDevice *pci_dev, int irq_num, int level)
+{
+ int irq_index, shift, pic_irq, pic_level;
+ uint32_t *p;
+
+ irq_num = pci_slot_get_pirq(pci_dev, irq_num);
+ irq_index = pci_dev->irq_index;
+ p = &pci_irq_levels[irq_num][irq_index >> 5];
+ shift = (irq_index & 0x1f);
+ *p = (*p & ~(1 << shift)) | (level << shift);
+
+ /* now we change the pic irq level according to the piix irq mappings */
+ pic_irq = piix3_state->dev.config[0x60 + irq_num];
+ if (pic_irq < 16) {
+ /* the pic level is the logical OR of all the PCI irqs mapped
+ to it */
+ pic_level = 0;
+#if (PCI_IRQ_WORDS == 2)
+ pic_level = ((pci_irq_levels[irq_num][0] |
+ pci_irq_levels[irq_num][1]) != 0);
+#else
+ {
+ int i;
+ pic_level = 0;
+ for(i = 0; i < PCI_IRQ_WORDS; i++) {
+ if (pci_irq_levels[irq_num][i]) {
+ pic_level = 1;
+ break;
+ }
+ }
+ }
+#endif
+ pic_set_irq(pic_irq, pic_level);
+ }
+}
+
+static void piix3_reset(PIIX3State *d)
+{
+ uint8_t *pci_conf = d->dev.config;
+
+ pci_conf[0x04] = 0x07; // master, memory and I/O
+ pci_conf[0x05] = 0x00;
+ pci_conf[0x06] = 0x00;
+ pci_conf[0x07] = 0x02; // PCI_status_devsel_medium
+ pci_conf[0x4c] = 0x4d;
+ pci_conf[0x4e] = 0x03;
+ pci_conf[0x4f] = 0x00;
+ pci_conf[0x60] = 0x80;
+ pci_conf[0x69] = 0x02;
+ pci_conf[0x70] = 0x80;
+ pci_conf[0x76] = 0x0c;
+ pci_conf[0x77] = 0x0c;
+ pci_conf[0x78] = 0x02;
+ pci_conf[0x79] = 0x00;
+ pci_conf[0x80] = 0x00;
+ pci_conf[0x82] = 0x00;
+ pci_conf[0xa0] = 0x08;
+ pci_conf[0xa0] = 0x08;
+ pci_conf[0xa2] = 0x00;
+ pci_conf[0xa3] = 0x00;
+ pci_conf[0xa4] = 0x00;
+ pci_conf[0xa5] = 0x00;
+ pci_conf[0xa6] = 0x00;
+ pci_conf[0xa7] = 0x00;
+ pci_conf[0xa8] = 0x0f;
+ pci_conf[0xaa] = 0x00;
+ pci_conf[0xab] = 0x00;
+ pci_conf[0xac] = 0x00;
+ pci_conf[0xae] = 0x00;
+}
+
+void piix3_init(PCIBus *bus)
+{
+ PIIX3State *d;
+ uint8_t *pci_conf;
+
+ d = (PIIX3State *)pci_register_device(bus, "PIIX3", sizeof(PIIX3State),
+ -1, NULL, NULL);
+ register_savevm("PIIX3", 0, 1, generic_pci_save, generic_pci_load, d);
+
+ piix3_state = d;
+ pci_conf = d->dev.config;
+
+ pci_conf[0x00] = 0x86; // Intel
+ pci_conf[0x01] = 0x80;
+ pci_conf[0x02] = 0x00; // 82371SB PIIX3 PCI-to-ISA bridge (Step A1)
+ pci_conf[0x03] = 0x70;
+ pci_conf[0x0a] = 0x01; // class_sub = PCI_ISA
+ pci_conf[0x0b] = 0x06; // class_base = PCI_bridge
+ pci_conf[0x0e] = 0x80; // header_type = PCI_multifunction, generic
+
+ piix3_reset(d);
+}
+
+/* PREP pci init */
+
+static inline void set_config(PCIBus *s, target_phys_addr_t addr)
+{
+ int devfn, i;
+
+ for(i = 0; i < 11; i++) {
+ if ((addr & (1 << (11 + i))) != 0)
+ break;
+ }
+ devfn = ((addr >> 8) & 7) | (i << 3);
+ s->config_reg = 0x80000000 | (addr & 0xfc) | (devfn << 8);
+}
+
+static void PPC_PCIIO_writeb (void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ PCIBus *s = opaque;
+ set_config(s, addr);
+ pci_data_write(s, addr, val, 1);
+}
+
+static void PPC_PCIIO_writew (void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ PCIBus *s = opaque;
+ set_config(s, addr);
+#ifdef TARGET_WORDS_BIGENDIAN
+ val = bswap16(val);
+#endif
+ pci_data_write(s, addr, val, 2);
+}
+
+static void PPC_PCIIO_writel (void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ PCIBus *s = opaque;
+ set_config(s, addr);
+#ifdef TARGET_WORDS_BIGENDIAN
+ val = bswap32(val);
+#endif
+ pci_data_write(s, addr, val, 4);
+}
+
+static uint32_t PPC_PCIIO_readb (void *opaque, target_phys_addr_t addr)
+{
+ PCIBus *s = opaque;
+ uint32_t val;
+ set_config(s, addr);
+ val = pci_data_read(s, addr, 1);
+ return val;
+}
+
+static uint32_t PPC_PCIIO_readw (void *opaque, target_phys_addr_t addr)
+{
+ PCIBus *s = opaque;
+ uint32_t val;
+ set_config(s, addr);
+ val = pci_data_read(s, addr, 2);
+#ifdef TARGET_WORDS_BIGENDIAN
+ val = bswap16(val);
+#endif
+ return val;
+}
+
+static uint32_t PPC_PCIIO_readl (void *opaque, target_phys_addr_t addr)
+{
+ PCIBus *s = opaque;
+ uint32_t val;
+ set_config(s, addr);
+ val = pci_data_read(s, addr, 4);
+#ifdef TARGET_WORDS_BIGENDIAN
+ val = bswap32(val);
+#endif
+ return val;
+}
+
+static CPUWriteMemoryFunc *PPC_PCIIO_write[] = {
+ &PPC_PCIIO_writeb,
+ &PPC_PCIIO_writew,
+ &PPC_PCIIO_writel,
+};
+
+static CPUReadMemoryFunc *PPC_PCIIO_read[] = {
+ &PPC_PCIIO_readb,
+ &PPC_PCIIO_readw,
+ &PPC_PCIIO_readl,
+};
+
+static void prep_set_irq(PCIDevice *d, int irq_num, int level)
+{
+ /* XXX: we do not simulate the hardware - we rely on the BIOS to
+ set correctly for irq line field */
+ pic_set_irq(d->config[PCI_INTERRUPT_LINE], level);
+}
+
+PCIBus *pci_prep_init(void)
+{
+ PCIBus *s;
+ PCIDevice *d;
+ int PPC_io_memory;
+
+ s = pci_register_bus();
+ s->set_irq = prep_set_irq;
+
+ PPC_io_memory = cpu_register_io_memory(0, PPC_PCIIO_read,
+ PPC_PCIIO_write, s);
+ cpu_register_physical_memory(0x80800000, 0x00400000, PPC_io_memory);
+
+ d = pci_register_device(s, "PREP PCI Bridge", sizeof(PCIDevice), 0,
+ NULL, NULL);
+
+ /* XXX: put correct IDs */
+ d->config[0x00] = 0x11; // vendor_id
+ d->config[0x01] = 0x10;
+ d->config[0x02] = 0x26; // device_id
+ d->config[0x03] = 0x00;
+ d->config[0x08] = 0x02; // revision
+ d->config[0x0a] = 0x04; // class_sub = pci2pci
+ d->config[0x0b] = 0x06; // class_base = PCI_bridge
+ d->config[0x0e] = 0x01; // header_type
+ return s;
+}
+
+
+/* pmac pci init */
+
+#if 0
+/* Grackle PCI host */
+static void pci_grackle_config_writel (void *opaque, target_phys_addr_t addr,
+ uint32_t val)
+{
+ PCIBus *s = opaque;
+#ifdef TARGET_WORDS_BIGENDIAN
+ val = bswap32(val);
+#endif
+ s->config_reg = val;
+}
+
+static uint32_t pci_grackle_config_readl (void *opaque, target_phys_addr_t addr)
+{
+ PCIBus *s = opaque;
+ uint32_t val;
+
+ val = s->config_reg;
+#ifdef TARGET_WORDS_BIGENDIAN
+ val = bswap32(val);
+#endif
+ return val;
+}
+
+static CPUWriteMemoryFunc *pci_grackle_config_write[] = {
+ &pci_grackle_config_writel,
+ &pci_grackle_config_writel,
+ &pci_grackle_config_writel,
+};
+
+static CPUReadMemoryFunc *pci_grackle_config_read[] = {
+ &pci_grackle_config_readl,
+ &pci_grackle_config_readl,
+ &pci_grackle_config_readl,
+};
+
+static void pci_grackle_writeb (void *opaque, target_phys_addr_t addr,
+ uint32_t val)
+{
+ PCIBus *s = opaque;
+ pci_data_write(s, addr, val, 1);
+}
+
+static void pci_grackle_writew (void *opaque, target_phys_addr_t addr,
+ uint32_t val)
+{
+ PCIBus *s = opaque;
+#ifdef TARGET_WORDS_BIGENDIAN
+ val = bswap16(val);
+#endif
+ pci_data_write(s, addr, val, 2);
+}
+
+static void pci_grackle_writel (void *opaque, target_phys_addr_t addr,
+ uint32_t val)
+{
+ PCIBus *s = opaque;
+#ifdef TARGET_WORDS_BIGENDIAN
+ val = bswap32(val);
+#endif
+ pci_data_write(s, addr, val, 4);
+}
+
+static uint32_t pci_grackle_readb (void *opaque, target_phys_addr_t addr)
+{
+ PCIBus *s = opaque;
+ uint32_t val;
+ val = pci_data_read(s, addr, 1);
+ return val;
+}
+
+static uint32_t pci_grackle_readw (void *opaque, target_phys_addr_t addr)
+{
+ PCIBus *s = opaque;
+ uint32_t val;
+ val = pci_data_read(s, addr, 2);
+#ifdef TARGET_WORDS_BIGENDIAN
+ val = bswap16(val);
+#endif
+ return val;
+}
+
+static uint32_t pci_grackle_readl (void *opaque, target_phys_addr_t addr)
+{
+ PCIBus *s = opaque;
+ uint32_t val;
+
+ val = pci_data_read(s, addr, 4);
+#ifdef TARGET_WORDS_BIGENDIAN
+ val = bswap32(val);
+#endif
+ return val;
+}
+
+static CPUWriteMemoryFunc *pci_grackle_write[] = {
+ &pci_grackle_writeb,
+ &pci_grackle_writew,
+ &pci_grackle_writel,
+};
+
+static CPUReadMemoryFunc *pci_grackle_read[] = {
+ &pci_grackle_readb,
+ &pci_grackle_readw,
+ &pci_grackle_readl,
+};
+#endif
+
+/* Uninorth PCI host (for all Mac99 and newer machines */
+static void pci_unin_main_config_writel (void *opaque, target_phys_addr_t addr,
+ uint32_t val)
+{
+ PCIBus *s = opaque;
+ int i;
+
+#ifdef TARGET_WORDS_BIGENDIAN
+ val = bswap32(val);
+#endif
+
+ for (i = 11; i < 32; i++) {
+ if ((val & (1 << i)) != 0)
+ break;
+ }
+#if 0
+ s->config_reg = 0x80000000 | (1 << 16) | (val & 0x7FC) | (i << 11);
+#else
+ s->config_reg = 0x80000000 | (0 << 16) | (val & 0x7FC) | (i << 11);
+#endif
+}
+
+static uint32_t pci_unin_main_config_readl (void *opaque,
+ target_phys_addr_t addr)
+{
+ PCIBus *s = opaque;
+ uint32_t val;
+ int devfn;
+
+ devfn = (s->config_reg >> 8) & 0xFF;
+ val = (1 << (devfn >> 3)) | ((devfn & 0x07) << 8) | (s->config_reg & 0xFC);
+#ifdef TARGET_WORDS_BIGENDIAN
+ val = bswap32(val);
+#endif
+
+ return val;
+}
+
+static CPUWriteMemoryFunc *pci_unin_main_config_write[] = {
+ &pci_unin_main_config_writel,
+ &pci_unin_main_config_writel,
+ &pci_unin_main_config_writel,
+};
+
+static CPUReadMemoryFunc *pci_unin_main_config_read[] = {
+ &pci_unin_main_config_readl,
+ &pci_unin_main_config_readl,
+ &pci_unin_main_config_readl,
+};
+
+static void pci_unin_main_writeb (void *opaque, target_phys_addr_t addr,
+ uint32_t val)
+{
+ PCIBus *s = opaque;
+ pci_data_write(s, addr & 7, val, 1);
+}
+
+static void pci_unin_main_writew (void *opaque, target_phys_addr_t addr,
+ uint32_t val)
+{
+ PCIBus *s = opaque;
+#ifdef TARGET_WORDS_BIGENDIAN
+ val = bswap16(val);
+#endif
+ pci_data_write(s, addr & 7, val, 2);
+}
+
+static void pci_unin_main_writel (void *opaque, target_phys_addr_t addr,
+ uint32_t val)
+{
+ PCIBus *s = opaque;
+#ifdef TARGET_WORDS_BIGENDIAN
+ val = bswap32(val);
+#endif
+ pci_data_write(s, addr & 7, val, 4);
+}
+
+static uint32_t pci_unin_main_readb (void *opaque, target_phys_addr_t addr)
+{
+ PCIBus *s = opaque;
+ uint32_t val;
+
+ val = pci_data_read(s, addr & 7, 1);
+
+ return val;
+}
+
+static uint32_t pci_unin_main_readw (void *opaque, target_phys_addr_t addr)
+{
+ PCIBus *s = opaque;
+ uint32_t val;
+
+ val = pci_data_read(s, addr & 7, 2);
+#ifdef TARGET_WORDS_BIGENDIAN
+ val = bswap16(val);
+#endif
+
+ return val;
+}
+
+static uint32_t pci_unin_main_readl (void *opaque, target_phys_addr_t addr)
+{
+ PCIBus *s = opaque;
+ uint32_t val;
+
+ val = pci_data_read(s, addr, 4);
+#ifdef TARGET_WORDS_BIGENDIAN
+ val = bswap32(val);
+#endif
+
+ return val;
+}
+
+static CPUWriteMemoryFunc *pci_unin_main_write[] = {
+ &pci_unin_main_writeb,
+ &pci_unin_main_writew,
+ &pci_unin_main_writel,
+};
+
+static CPUReadMemoryFunc *pci_unin_main_read[] = {
+ &pci_unin_main_readb,
+ &pci_unin_main_readw,
+ &pci_unin_main_readl,
+};
+
+#if 0
+
+static void pci_unin_config_writel (void *opaque, target_phys_addr_t addr,
+ uint32_t val)
+{
+ PCIBus *s = opaque;
+
+#ifdef TARGET_WORDS_BIGENDIAN
+ val = bswap32(val);
+#endif
+ s->config_reg = 0x80000000 | (val & ~0x00000001);
+}
+
+static uint32_t pci_unin_config_readl (void *opaque,
+ target_phys_addr_t addr)
+{
+ PCIBus *s = opaque;
+ uint32_t val;
+
+ val = (s->config_reg | 0x00000001) & ~0x80000000;
+#ifdef TARGET_WORDS_BIGENDIAN
+ val = bswap32(val);
+#endif
+
+ return val;
+}
+
+static CPUWriteMemoryFunc *pci_unin_config_write[] = {
+ &pci_unin_config_writel,
+ &pci_unin_config_writel,
+ &pci_unin_config_writel,
+};
+
+static CPUReadMemoryFunc *pci_unin_config_read[] = {
+ &pci_unin_config_readl,
+ &pci_unin_config_readl,
+ &pci_unin_config_readl,
+};
+
+static void pci_unin_writeb (void *opaque, target_phys_addr_t addr,
+ uint32_t val)
+{
+ PCIBus *s = opaque;
+ pci_data_write(s, addr & 3, val, 1);
+}
+
+static void pci_unin_writew (void *opaque, target_phys_addr_t addr,
+ uint32_t val)
+{
+ PCIBus *s = opaque;
+#ifdef TARGET_WORDS_BIGENDIAN
+ val = bswap16(val);
+#endif
+ pci_data_write(s, addr & 3, val, 2);
+}
+
+static void pci_unin_writel (void *opaque, target_phys_addr_t addr,
+ uint32_t val)
+{
+ PCIBus *s = opaque;
+#ifdef TARGET_WORDS_BIGENDIAN
+ val = bswap32(val);
+#endif
+ pci_data_write(s, addr & 3, val, 4);
+}
+
+static uint32_t pci_unin_readb (void *opaque, target_phys_addr_t addr)
+{
+ PCIBus *s = opaque;
+ uint32_t val;
+
+ val = pci_data_read(s, addr & 3, 1);
+
+ return val;
+}
+
+static uint32_t pci_unin_readw (void *opaque, target_phys_addr_t addr)
+{
+ PCIBus *s = opaque;
+ uint32_t val;
+
+ val = pci_data_read(s, addr & 3, 2);
+#ifdef TARGET_WORDS_BIGENDIAN
+ val = bswap16(val);
+#endif
+
+ return val;
+}
+
+static uint32_t pci_unin_readl (void *opaque, target_phys_addr_t addr)
+{
+ PCIBus *s = opaque;
+ uint32_t val;
+
+ val = pci_data_read(s, addr & 3, 4);
+#ifdef TARGET_WORDS_BIGENDIAN
+ val = bswap32(val);
+#endif
+
+ return val;
+}
+
+static CPUWriteMemoryFunc *pci_unin_write[] = {
+ &pci_unin_writeb,
+ &pci_unin_writew,
+ &pci_unin_writel,
+};
+
+static CPUReadMemoryFunc *pci_unin_read[] = {
+ &pci_unin_readb,
+ &pci_unin_readw,
+ &pci_unin_readl,
+};
+#endif
+
+static void pmac_set_irq(PCIDevice *d, int irq_num, int level)
+{
+ openpic_t *openpic;
+ /* XXX: we do not simulate the hardware - we rely on the BIOS to
+ set correctly for irq line field */
+ openpic = d->bus->openpic;
+#ifdef TARGET_PPC
+ if (openpic)
+ openpic_set_irq(openpic, d->config[PCI_INTERRUPT_LINE], level);
+#endif
+}
+
+void pci_pmac_set_openpic(PCIBus *bus, openpic_t *openpic)
+{
+ bus->openpic = openpic;
+}
+
+PCIBus *pci_pmac_init(void)
+{
+ PCIBus *s;
+ PCIDevice *d;
+ int pci_mem_config, pci_mem_data;
+
+ /* Use values found on a real PowerMac */
+ /* Uninorth main bus */
+ s = pci_register_bus();
+ s->set_irq = pmac_set_irq;
+
+ pci_mem_config = cpu_register_io_memory(0, pci_unin_main_config_read,
+ pci_unin_main_config_write, s);
+ pci_mem_data = cpu_register_io_memory(0, pci_unin_main_read,
+ pci_unin_main_write, s);
+ cpu_register_physical_memory(0xf2800000, 0x1000, pci_mem_config);
+ cpu_register_physical_memory(0xf2c00000, 0x1000, pci_mem_data);
+ s->devfn_min = 11 << 3;
+ d = pci_register_device(s, "Uni-north main", sizeof(PCIDevice),
+ 11 << 3, NULL, NULL);
+ d->config[0x00] = 0x6b; // vendor_id : Apple
+ d->config[0x01] = 0x10;
+ d->config[0x02] = 0x1F; // device_id
+ d->config[0x03] = 0x00;
+ d->config[0x08] = 0x00; // revision
+ d->config[0x0A] = 0x00; // class_sub = pci host
+ d->config[0x0B] = 0x06; // class_base = PCI_bridge
+ d->config[0x0C] = 0x08; // cache_line_size
+ d->config[0x0D] = 0x10; // latency_timer
+ d->config[0x0E] = 0x00; // header_type
+ d->config[0x34] = 0x00; // capabilities_pointer
+
+#if 0 // XXX: not activated as PPC BIOS doesn't handle mutiple buses properly
+ /* pci-to-pci bridge */
+ d = pci_register_device("Uni-north bridge", sizeof(PCIDevice), 0, 13 << 3,
+ NULL, NULL);
+ d->config[0x00] = 0x11; // vendor_id : TI
+ d->config[0x01] = 0x10;
+ d->config[0x02] = 0x26; // device_id
+ d->config[0x03] = 0x00;
+ d->config[0x08] = 0x05; // revision
+ d->config[0x0A] = 0x04; // class_sub = pci2pci
+ d->config[0x0B] = 0x06; // class_base = PCI_bridge
+ d->config[0x0C] = 0x08; // cache_line_size
+ d->config[0x0D] = 0x20; // latency_timer
+ d->config[0x0E] = 0x01; // header_type
+
+ d->config[0x18] = 0x01; // primary_bus
+ d->config[0x19] = 0x02; // secondary_bus
+ d->config[0x1A] = 0x02; // subordinate_bus
+ d->config[0x1B] = 0x20; // secondary_latency_timer
+ d->config[0x1C] = 0x11; // io_base
+ d->config[0x1D] = 0x01; // io_limit
+ d->config[0x20] = 0x00; // memory_base
+ d->config[0x21] = 0x80;
+ d->config[0x22] = 0x00; // memory_limit
+ d->config[0x23] = 0x80;
+ d->config[0x24] = 0x01; // prefetchable_memory_base
+ d->config[0x25] = 0x80;
+ d->config[0x26] = 0xF1; // prefectchable_memory_limit
+ d->config[0x27] = 0x7F;
+ // d->config[0x34] = 0xdc // capabilities_pointer
+#endif
+#if 0 // XXX: not needed for now
+ /* Uninorth AGP bus */
+ s = &pci_bridge[1];
+ pci_mem_config = cpu_register_io_memory(0, pci_unin_config_read,
+ pci_unin_config_write, s);
+ pci_mem_data = cpu_register_io_memory(0, pci_unin_read,
+ pci_unin_write, s);
+ cpu_register_physical_memory(0xf0800000, 0x1000, pci_mem_config);
+ cpu_register_physical_memory(0xf0c00000, 0x1000, pci_mem_data);
+
+ d = pci_register_device("Uni-north AGP", sizeof(PCIDevice), 0, 11 << 3,
+ NULL, NULL);
+ d->config[0x00] = 0x6b; // vendor_id : Apple
+ d->config[0x01] = 0x10;
+ d->config[0x02] = 0x20; // device_id
+ d->config[0x03] = 0x00;
+ d->config[0x08] = 0x00; // revision
+ d->config[0x0A] = 0x00; // class_sub = pci host
+ d->config[0x0B] = 0x06; // class_base = PCI_bridge
+ d->config[0x0C] = 0x08; // cache_line_size
+ d->config[0x0D] = 0x10; // latency_timer
+ d->config[0x0E] = 0x00; // header_type
+ // d->config[0x34] = 0x80; // capabilities_pointer
+#endif
+
+#if 0 // XXX: not needed for now
+ /* Uninorth internal bus */
+ s = &pci_bridge[2];
+ pci_mem_config = cpu_register_io_memory(0, pci_unin_config_read,
+ pci_unin_config_write, s);
+ pci_mem_data = cpu_register_io_memory(0, pci_unin_read,
+ pci_unin_write, s);
+ cpu_register_physical_memory(0xf4800000, 0x1000, pci_mem_config);
+ cpu_register_physical_memory(0xf4c00000, 0x1000, pci_mem_data);
+
+ d = pci_register_device("Uni-north internal", sizeof(PCIDevice),
+ 3, 11 << 3, NULL, NULL);
+ d->config[0x00] = 0x6b; // vendor_id : Apple
+ d->config[0x01] = 0x10;
+ d->config[0x02] = 0x1E; // device_id
+ d->config[0x03] = 0x00;
+ d->config[0x08] = 0x00; // revision
+ d->config[0x0A] = 0x00; // class_sub = pci host
+ d->config[0x0B] = 0x06; // class_base = PCI_bridge
+ d->config[0x0C] = 0x08; // cache_line_size
+ d->config[0x0D] = 0x10; // latency_timer
+ d->config[0x0E] = 0x00; // header_type
+ d->config[0x34] = 0x00; // capabilities_pointer
+#endif
+
+#if 0 // Grackle ?
+ /* same values as PearPC - check this */
+ d->config[0x00] = 0x11; // vendor_id
+ d->config[0x01] = 0x10;
+ d->config[0x02] = 0x26; // device_id
+ d->config[0x03] = 0x00;
+ d->config[0x08] = 0x02; // revision
+ d->config[0x0a] = 0x04; // class_sub = pci2pci
+ d->config[0x0b] = 0x06; // class_base = PCI_bridge
+ d->config[0x0e] = 0x01; // header_type
+
+ d->config[0x18] = 0x0; // primary_bus
+ d->config[0x19] = 0x1; // secondary_bus
+ d->config[0x1a] = 0x1; // subordinate_bus
+ d->config[0x1c] = 0x10; // io_base
+ d->config[0x1d] = 0x20; // io_limit
+
+ d->config[0x20] = 0x80; // memory_base
+ d->config[0x21] = 0x80;
+ d->config[0x22] = 0x90; // memory_limit
+ d->config[0x23] = 0x80;
+
+ d->config[0x24] = 0x00; // prefetchable_memory_base
+ d->config[0x25] = 0x84;
+ d->config[0x26] = 0x00; // prefetchable_memory_limit
+ d->config[0x27] = 0x85;
+#endif
+ return s;
+}
+
+/***********************************************************/
+/* generic PCI irq support */
+
+/* 0 <= irq_num <= 3. level must be 0 or 1 */
+void pci_set_irq(PCIDevice *pci_dev, int irq_num, int level)
+{
+ PCIBus *bus = pci_dev->bus;
+ bus->set_irq(pci_dev, irq_num, level);
+}
+
+/***********************************************************/
+/* monitor info on PCI */
+
+static void pci_info_device(PCIDevice *d)
+{
+ int i, class;
+ PCIIORegion *r;
+
+ term_printf(" Bus %2d, device %3d, function %d:\n",
+ d->bus->bus_num, d->devfn >> 3, d->devfn & 7);
+ class = le16_to_cpu(*((uint16_t *)(d->config + PCI_CLASS_DEVICE)));
+ term_printf(" ");
+ switch(class) {
+ case 0x0101:
+ term_printf("IDE controller");
+ break;
+ case 0x0200:
+ term_printf("Ethernet controller");
+ break;
+ case 0x0300:
+ term_printf("VGA controller");
+ break;
+ default:
+ term_printf("Class %04x", class);
+ break;
+ }
+ term_printf(": PCI device %04x:%04x\n",
+ le16_to_cpu(*((uint16_t *)(d->config + PCI_VENDOR_ID))),
+ le16_to_cpu(*((uint16_t *)(d->config + PCI_DEVICE_ID))));
+
+ if (d->config[PCI_INTERRUPT_PIN] != 0) {
+ term_printf(" IRQ %d.\n", d->config[PCI_INTERRUPT_LINE]);
+ }
+ for(i = 0;i < PCI_NUM_REGIONS; i++) {
+ r = &d->io_regions[i];
+ if (r->size != 0) {
+ term_printf(" BAR%d: ", i);
+ if (r->type & PCI_ADDRESS_SPACE_IO) {
+ term_printf("I/O at 0x%04x [0x%04x].\n",
+ r->addr, r->addr + r->size - 1);
+ } else {
+ term_printf("32 bit memory at 0x%08x [0x%08x].\n",
+ r->addr, r->addr + r->size - 1);
+ }
+ }
+ }
+}
+
+void pci_info(void)
+{
+ PCIBus *bus = first_bus;
+ PCIDevice *d;
+ int devfn;
+
+ if (bus) {
+ for(devfn = 0; devfn < 256; devfn++) {
+ d = bus->devices[devfn];
+ if (d)
+ pci_info_device(d);
+ }
+ }
+}
+
+/***********************************************************/
+/* XXX: the following should be moved to the PC BIOS */
+
+static __attribute__((unused)) uint32_t isa_inb(uint32_t addr)
+{
+ return cpu_inb(cpu_single_env, addr);
+}
+
+static void isa_outb(uint32_t val, uint32_t addr)
+{
+ cpu_outb(cpu_single_env, addr, val);
+}
+
+static __attribute__((unused)) uint32_t isa_inw(uint32_t addr)
+{
+ return cpu_inw(cpu_single_env, addr);
+}
+
+static __attribute__((unused)) void isa_outw(uint32_t val, uint32_t addr)
+{
+ cpu_outw(cpu_single_env, addr, val);
+}
+
+static __attribute__((unused)) uint32_t isa_inl(uint32_t addr)
+{
+ return cpu_inl(cpu_single_env, addr);
+}
+
+static __attribute__((unused)) void isa_outl(uint32_t val, uint32_t addr)
+{
+ cpu_outl(cpu_single_env, addr, val);
+}
+
+static void pci_config_writel(PCIDevice *d, uint32_t addr, uint32_t val)
+{
+ PCIBus *s = d->bus;
+ s->config_reg = 0x80000000 | (s->bus_num << 16) |
+ (d->devfn << 8) | addr;
+ pci_data_write(s, 0, val, 4);
+}
+
+static void pci_config_writew(PCIDevice *d, uint32_t addr, uint32_t val)
+{
+ PCIBus *s = d->bus;
+ s->config_reg = 0x80000000 | (s->bus_num << 16) |
+ (d->devfn << 8) | (addr & ~3);
+ pci_data_write(s, addr & 3, val, 2);
+}
+
+static void pci_config_writeb(PCIDevice *d, uint32_t addr, uint32_t val)
+{
+ PCIBus *s = d->bus;
+ s->config_reg = 0x80000000 | (s->bus_num << 16) |
+ (d->devfn << 8) | (addr & ~3);
+ pci_data_write(s, addr & 3, val, 1);
+}
+
+static __attribute__((unused)) uint32_t pci_config_readl(PCIDevice *d, uint32_t addr)
+{
+ PCIBus *s = d->bus;
+ s->config_reg = 0x80000000 | (s->bus_num << 16) |
+ (d->devfn << 8) | addr;
+ return pci_data_read(s, 0, 4);
+}
+
+static uint32_t pci_config_readw(PCIDevice *d, uint32_t addr)
+{
+ PCIBus *s = d->bus;
+ s->config_reg = 0x80000000 | (s->bus_num << 16) |
+ (d->devfn << 8) | (addr & ~3);
+ return pci_data_read(s, addr & 3, 2);
+}
+
+static uint32_t pci_config_readb(PCIDevice *d, uint32_t addr)
+{
+ PCIBus *s = d->bus;
+ s->config_reg = 0x80000000 | (s->bus_num << 16) |
+ (d->devfn << 8) | (addr & ~3);
+ return pci_data_read(s, addr & 3, 1);
+}
+
+static uint32_t pci_bios_io_addr;
+static uint32_t pci_bios_mem_addr;
+/* host irqs corresponding to PCI irqs A-D */
+static uint8_t pci_irqs[4] = { 11, 9, 11, 9 };
+
+static void pci_set_io_region_addr(PCIDevice *d, int region_num, uint32_t addr)
+{
+ PCIIORegion *r;
+ uint16_t cmd;
+ uint32_t ofs;
+
+ if ( region_num == PCI_ROM_SLOT ) {
+ ofs = 0x30;
+ }else{
+ ofs = 0x10 + region_num * 4;
+ }
+
+ pci_config_writel(d, ofs, addr);
+ r = &d->io_regions[region_num];
+
+ /* enable memory mappings */
+ cmd = pci_config_readw(d, PCI_COMMAND);
+ if ( region_num == PCI_ROM_SLOT )
+ cmd |= 2;
+ else if (r->type & PCI_ADDRESS_SPACE_IO)
+ cmd |= 1;
+ else
+ cmd |= 2;
+ pci_config_writew(d, PCI_COMMAND, cmd);
+}
+
+static void pci_bios_init_device(PCIDevice *d)
+{
+ int class;
+ PCIIORegion *r;
+ uint32_t *paddr;
+ int i, pin, pic_irq, vendor_id, device_id;
+
+ class = pci_config_readw(d, PCI_CLASS_DEVICE);
+ vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
+ device_id = pci_config_readw(d, PCI_DEVICE_ID);
+ switch(class) {
+ case 0x0101:
+ if (vendor_id == 0x8086 && device_id == 0x7010) {
+ /* PIIX3 IDE */
+ pci_config_writew(d, 0x40, 0x8000); // enable IDE0
+ pci_config_writew(d, 0x42, 0x8000); // enable IDE1
+ goto default_map;
+ } else {
+ /* IDE: we map it as in ISA mode */
+ pci_set_io_region_addr(d, 0, 0x1f0);
+ pci_set_io_region_addr(d, 1, 0x3f4);
+ pci_set_io_region_addr(d, 2, 0x170);
+ pci_set_io_region_addr(d, 3, 0x374);
+ }
+ break;
+ case 0x0300:
+ if (vendor_id != 0x1234)
+ goto default_map;
+ /* VGA: map frame buffer to default Bochs VBE address */
+ pci_set_io_region_addr(d, 0, 0xE0000000);
+ break;
+ case 0x0800:
+ /* PIC */
+ vendor_id = pci_config_readw(d, PCI_VENDOR_ID);
+ device_id = pci_config_readw(d, PCI_DEVICE_ID);
+ if (vendor_id == 0x1014) {
+ /* IBM */
+ if (device_id == 0x0046 || device_id == 0xFFFF) {
+ /* MPIC & MPIC2 */
+ pci_set_io_region_addr(d, 0, 0x80800000 + 0x00040000);
+ }
+ }
+ break;
+ case 0xff00:
+ if (vendor_id == 0x0106b &&
+ (device_id == 0x0017 || device_id == 0x0022)) {
+ /* macio bridge */
+ pci_set_io_region_addr(d, 0, 0x80800000);
+ }
+ break;
+ default:
+ default_map:
+ /* default memory mappings */
+ for(i = 0; i < PCI_NUM_REGIONS; i++) {
+ r = &d->io_regions[i];
+ if (r->size) {
+ if (r->type & PCI_ADDRESS_SPACE_IO)
+ paddr = &pci_bios_io_addr;
+ else
+ paddr = &pci_bios_mem_addr;
+ *paddr = (*paddr + r->size - 1) & ~(r->size - 1);
+ pci_set_io_region_addr(d, i, *paddr);
+ *paddr += r->size;
+ }
+ }
+ break;
+ }
+
+ /* map the interrupt */
+ pin = pci_config_readb(d, PCI_INTERRUPT_PIN);
+ if (pin != 0) {
+ pin = pci_slot_get_pirq(d, pin - 1);
+ pic_irq = pci_irqs[pin];
+ pci_config_writeb(d, PCI_INTERRUPT_LINE, pic_irq);
+ }
+}
+
+/*
+ * This function initializes the PCI devices as a normal PCI BIOS
+ * would do. It is provided just in case the BIOS has no support for
+ * PCI.
+ */
+void pci_bios_init(void)
+{
+ PCIBus *bus;
+ PCIDevice *d;
+ int devfn, i, irq;
+ uint8_t elcr[2];
+
+ pci_bios_io_addr = 0xc000;
+ pci_bios_mem_addr = 0xf0000000;
+
+ /* activate IRQ mappings */
+ elcr[0] = 0x00;
+ elcr[1] = 0x00;
+ for(i = 0; i < 4; i++) {
+ irq = pci_irqs[i];
+ /* set to trigger level */
+ elcr[irq >> 3] |= (1 << (irq & 7));
+ /* activate irq remapping in PIIX */
+ pci_config_writeb((PCIDevice *)piix3_state, 0x60 + i, irq);
+ }
+ isa_outb(elcr[0], 0x4d0);
+ isa_outb(elcr[1], 0x4d1);
+
+ bus = first_bus;
+ if (bus) {
+ for(devfn = 0; devfn < 256; devfn++) {
+ d = bus->devices[devfn];
+ if (d)
+ pci_bios_init_device(d);
+ }
+ }
+}
--- /dev/null
+/*
+ * QEMU PC keyboard emulation
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+
+/* debug PC keyboard */
+//#define DEBUG_KBD
+
+/* debug PC keyboard : only mouse */
+//#define DEBUG_MOUSE
+
+/* Keyboard Controller Commands */
+#define KBD_CCMD_READ_MODE 0x20 /* Read mode bits */
+#define KBD_CCMD_WRITE_MODE 0x60 /* Write mode bits */
+#define KBD_CCMD_GET_VERSION 0xA1 /* Get controller version */
+#define KBD_CCMD_MOUSE_DISABLE 0xA7 /* Disable mouse interface */
+#define KBD_CCMD_MOUSE_ENABLE 0xA8 /* Enable mouse interface */
+#define KBD_CCMD_TEST_MOUSE 0xA9 /* Mouse interface test */
+#define KBD_CCMD_SELF_TEST 0xAA /* Controller self test */
+#define KBD_CCMD_KBD_TEST 0xAB /* Keyboard interface test */
+#define KBD_CCMD_KBD_DISABLE 0xAD /* Keyboard interface disable */
+#define KBD_CCMD_KBD_ENABLE 0xAE /* Keyboard interface enable */
+#define KBD_CCMD_READ_INPORT 0xC0 /* read input port */
+#define KBD_CCMD_READ_OUTPORT 0xD0 /* read output port */
+#define KBD_CCMD_WRITE_OUTPORT 0xD1 /* write output port */
+#define KBD_CCMD_WRITE_OBUF 0xD2
+#define KBD_CCMD_WRITE_AUX_OBUF 0xD3 /* Write to output buffer as if
+ initiated by the auxiliary device */
+#define KBD_CCMD_WRITE_MOUSE 0xD4 /* Write the following byte to the mouse */
+#define KBD_CCMD_DISABLE_A20 0xDD /* HP vectra only ? */
+#define KBD_CCMD_ENABLE_A20 0xDF /* HP vectra only ? */
+#define KBD_CCMD_RESET 0xFE
+
+/* Keyboard Commands */
+#define KBD_CMD_SET_LEDS 0xED /* Set keyboard leds */
+#define KBD_CMD_ECHO 0xEE
+#define KBD_CMD_GET_ID 0xF2 /* get keyboard ID */
+#define KBD_CMD_SET_RATE 0xF3 /* Set typematic rate */
+#define KBD_CMD_ENABLE 0xF4 /* Enable scanning */
+#define KBD_CMD_RESET_DISABLE 0xF5 /* reset and disable scanning */
+#define KBD_CMD_RESET_ENABLE 0xF6 /* reset and enable scanning */
+#define KBD_CMD_RESET 0xFF /* Reset */
+
+/* Keyboard Replies */
+#define KBD_REPLY_POR 0xAA /* Power on reset */
+#define KBD_REPLY_ACK 0xFA /* Command ACK */
+#define KBD_REPLY_RESEND 0xFE /* Command NACK, send the cmd again */
+
+/* Status Register Bits */
+#define KBD_STAT_OBF 0x01 /* Keyboard output buffer full */
+#define KBD_STAT_IBF 0x02 /* Keyboard input buffer full */
+#define KBD_STAT_SELFTEST 0x04 /* Self test successful */
+#define KBD_STAT_CMD 0x08 /* Last write was a command write (0=data) */
+#define KBD_STAT_UNLOCKED 0x10 /* Zero if keyboard locked */
+#define KBD_STAT_MOUSE_OBF 0x20 /* Mouse output buffer full */
+#define KBD_STAT_GTO 0x40 /* General receive/xmit timeout */
+#define KBD_STAT_PERR 0x80 /* Parity error */
+
+/* Controller Mode Register Bits */
+#define KBD_MODE_KBD_INT 0x01 /* Keyboard data generate IRQ1 */
+#define KBD_MODE_MOUSE_INT 0x02 /* Mouse data generate IRQ12 */
+#define KBD_MODE_SYS 0x04 /* The system flag (?) */
+#define KBD_MODE_NO_KEYLOCK 0x08 /* The keylock doesn't affect the keyboard if set */
+#define KBD_MODE_DISABLE_KBD 0x10 /* Disable keyboard interface */
+#define KBD_MODE_DISABLE_MOUSE 0x20 /* Disable mouse interface */
+#define KBD_MODE_KCC 0x40 /* Scan code conversion to PC format */
+#define KBD_MODE_RFU 0x80
+
+/* Mouse Commands */
+#define AUX_SET_SCALE11 0xE6 /* Set 1:1 scaling */
+#define AUX_SET_SCALE21 0xE7 /* Set 2:1 scaling */
+#define AUX_SET_RES 0xE8 /* Set resolution */
+#define AUX_GET_SCALE 0xE9 /* Get scaling factor */
+/* according to Synaptic docs this $E9 is really 3-byte status */
+#define AUX_SET_STREAM 0xEA /* Set stream mode */
+#define AUX_POLL 0xEB /* Poll */
+#define AUX_RESET_WRAP 0xEC /* Reset wrap mode */
+#define AUX_SET_WRAP 0xEE /* Set wrap mode */
+#define AUX_SET_REMOTE 0xF0 /* Set remote mode */
+#define AUX_GET_TYPE 0xF2 /* Get type */
+#define AUX_SET_SAMPLE 0xF3 /* Set sample rate */
+#define AUX_ENABLE_DEV 0xF4 /* Enable aux device */
+#define AUX_DISABLE_DEV 0xF5 /* Disable aux device */
+#define AUX_SET_DEFAULT 0xF6
+#define AUX_RESET 0xFF /* Reset aux device */
+#define AUX_ACK 0xFA /* Command byte ACK. */
+
+#define MOUSE_STATUS_REMOTE 0x40
+#define MOUSE_STATUS_ENABLED 0x20
+#define MOUSE_STATUS_SCALE21 0x10
+
+#define KBD_QUEUE_SIZE 256
+
+typedef struct {
+ uint8_t aux[KBD_QUEUE_SIZE];
+ uint8_t data[KBD_QUEUE_SIZE];
+ int rptr, wptr, count;
+} KBDQueue;
+
+typedef struct {
+ int absolute;
+ int high;
+} TouchPad;
+
+typedef struct KBDState {
+ KBDQueue queue;
+ uint8_t write_cmd; /* if non zero, write data to port 60 is expected */
+ uint8_t status;
+ uint8_t mode;
+ /* keyboard state */
+ int kbd_write_cmd;
+ int scan_enabled;
+ /* mouse state */
+ int mouse_write_cmd;
+ uint8_t mouse_status;
+ uint8_t mouse_resolution;
+ uint8_t mouse_sample_rate;
+ uint8_t mouse_wrap;
+ uint8_t mouse_type; /* 0 = PS2, 3 = IMPS/2, 4 = IMEX */
+ uint8_t mouse_detect_state;
+ int mouse_dx; /* current values, needed for 'poll' mode */
+ int mouse_dy;
+ int mouse_dz;
+ uint8_t mouse_buttons;
+ TouchPad touchpad;
+} KBDState;
+
+KBDState kbd_state;
+
+/* update irq and KBD_STAT_[MOUSE_]OBF */
+/* XXX: not generating the irqs if KBD_MODE_DISABLE_KBD is set may be
+ incorrect, but it avoids having to simulate exact delays */
+static void kbd_update_irq(KBDState *s)
+{
+ KBDQueue *q = &s->queue;
+ int irq12_level, irq1_level;
+
+ irq1_level = 0;
+ irq12_level = 0;
+ s->status &= ~(KBD_STAT_OBF | KBD_STAT_MOUSE_OBF);
+ if (q->count != 0) {
+ s->status |= KBD_STAT_OBF;
+ if (q->aux[q->rptr]) {
+ s->status |= KBD_STAT_MOUSE_OBF;
+ if (s->mode & KBD_MODE_MOUSE_INT)
+ irq12_level = 1;
+ } else {
+ if ((s->mode & KBD_MODE_KBD_INT) &&
+ !(s->mode & KBD_MODE_DISABLE_KBD))
+ irq1_level = 1;
+ }
+ }
+ pic_set_irq(1, irq1_level);
+ pic_set_irq(12, irq12_level);
+}
+
+static void kbd_queue(KBDState *s, int b, int aux)
+{
+ KBDQueue *q = &s->queue;
+
+#if defined(DEBUG_MOUSE) || defined(DEBUG_KBD)
+ if (aux)
+ printf("mouse event: 0x%02x\n", b);
+#ifdef DEBUG_KBD
+ else
+ printf("kbd event: 0x%02x\n", b);
+#endif
+#endif
+ if (q->count >= KBD_QUEUE_SIZE)
+ return;
+ q->aux[q->wptr] = aux;
+ q->data[q->wptr] = b;
+ if (++q->wptr == KBD_QUEUE_SIZE)
+ q->wptr = 0;
+ q->count++;
+ kbd_update_irq(s);
+}
+
+static void pc_kbd_put_keycode(void *opaque, int keycode)
+{
+ KBDState *s = opaque;
+ kbd_queue(s, keycode, 0);
+}
+
+static uint32_t kbd_read_status(void *opaque, uint32_t addr)
+{
+ KBDState *s = opaque;
+ int val;
+ val = s->status;
+#if defined(DEBUG_KBD)
+ printf("kbd: read status=0x%02x\n", val);
+#endif
+ return val;
+}
+
+static void kbd_write_command(void *opaque, uint32_t addr, uint32_t val)
+{
+ KBDState *s = opaque;
+
+#ifdef DEBUG_KBD
+ printf("kbd: write cmd=0x%02x\n", val);
+#endif
+ switch(val) {
+ case KBD_CCMD_READ_MODE:
+ kbd_queue(s, s->mode, 0);
+ break;
+ case KBD_CCMD_WRITE_MODE:
+ case KBD_CCMD_WRITE_OBUF:
+ case KBD_CCMD_WRITE_AUX_OBUF:
+ case KBD_CCMD_WRITE_MOUSE:
+ case KBD_CCMD_WRITE_OUTPORT:
+ s->write_cmd = val;
+ break;
+ case KBD_CCMD_MOUSE_DISABLE:
+ s->mode |= KBD_MODE_DISABLE_MOUSE;
+ break;
+ case KBD_CCMD_MOUSE_ENABLE:
+ s->mode &= ~KBD_MODE_DISABLE_MOUSE;
+ break;
+ case KBD_CCMD_TEST_MOUSE:
+ kbd_queue(s, 0x00, 0);
+ break;
+ case KBD_CCMD_SELF_TEST:
+ s->status |= KBD_STAT_SELFTEST;
+ kbd_queue(s, 0x55, 0);
+ break;
+ case KBD_CCMD_KBD_TEST:
+ kbd_queue(s, 0x00, 0);
+ break;
+ case KBD_CCMD_KBD_DISABLE:
+ s->mode |= KBD_MODE_DISABLE_KBD;
+ kbd_update_irq(s);
+ break;
+ case KBD_CCMD_KBD_ENABLE:
+ s->mode &= ~KBD_MODE_DISABLE_KBD;
+ kbd_update_irq(s);
+ break;
+ case KBD_CCMD_READ_INPORT:
+ kbd_queue(s, 0x00, 0);
+ break;
+ case KBD_CCMD_READ_OUTPORT:
+ /* XXX: check that */
+#ifdef TARGET_I386
+ val = 0x01 | (((cpu_single_env->a20_mask >> 20) & 1) << 1);
+#else
+ val = 0x01;
+#endif
+ if (s->status & KBD_STAT_OBF)
+ val |= 0x10;
+ if (s->status & KBD_STAT_MOUSE_OBF)
+ val |= 0x20;
+ kbd_queue(s, val, 0);
+ break;
+#ifdef TARGET_I386
+ case KBD_CCMD_ENABLE_A20:
+ cpu_x86_set_a20(cpu_single_env, 1);
+ break;
+ case KBD_CCMD_DISABLE_A20:
+ cpu_x86_set_a20(cpu_single_env, 0);
+ break;
+#endif
+ case KBD_CCMD_RESET:
+ qemu_system_reset_request();
+ break;
+ case 0xff:
+ /* ignore that - I don't know what is its use */
+ break;
+ default:
+ fprintf(stderr, "qemu: unsupported keyboard cmd=0x%02x\n", val);
+ break;
+ }
+}
+
+static uint32_t kbd_read_data(void *opaque, uint32_t addr)
+{
+ KBDState *s = opaque;
+ KBDQueue *q;
+ int val, index, aux;
+
+ q = &s->queue;
+ if (q->count == 0) {
+ /* NOTE: if no data left, we return the last keyboard one
+ (needed for EMM386) */
+ /* XXX: need a timer to do things correctly */
+ index = q->rptr - 1;
+ if (index < 0)
+ index = KBD_QUEUE_SIZE - 1;
+ val = q->data[index];
+ } else {
+ aux = q->aux[q->rptr];
+ val = q->data[q->rptr];
+ if (++q->rptr == KBD_QUEUE_SIZE)
+ q->rptr = 0;
+ q->count--;
+ /* reading deasserts IRQ */
+ if (aux)
+ pic_set_irq(12, 0);
+ else
+ pic_set_irq(1, 0);
+ }
+ /* reassert IRQs if data left */
+ kbd_update_irq(s);
+#ifdef DEBUG_KBD
+ printf("kbd: read data=0x%02x\n", val);
+#endif
+ return val;
+}
+
+static void kbd_reset_keyboard(KBDState *s)
+{
+ s->scan_enabled = 1;
+}
+
+static void kbd_write_keyboard(KBDState *s, int val)
+{
+ switch(s->kbd_write_cmd) {
+ default:
+ case -1:
+ switch(val) {
+ case 0x00:
+ kbd_queue(s, KBD_REPLY_ACK, 0);
+ break;
+ case 0x05:
+ kbd_queue(s, KBD_REPLY_RESEND, 0);
+ break;
+ case KBD_CMD_GET_ID:
+ kbd_queue(s, KBD_REPLY_ACK, 0);
+ kbd_queue(s, 0xab, 0);
+ kbd_queue(s, 0x83, 0);
+ break;
+ case KBD_CMD_ECHO:
+ kbd_queue(s, KBD_CMD_ECHO, 0);
+ break;
+ case KBD_CMD_ENABLE:
+ s->scan_enabled = 1;
+ kbd_queue(s, KBD_REPLY_ACK, 0);
+ break;
+ case KBD_CMD_SET_LEDS:
+ case KBD_CMD_SET_RATE:
+ s->kbd_write_cmd = val;
+ kbd_queue(s, KBD_REPLY_ACK, 0);
+ break;
+ case KBD_CMD_RESET_DISABLE:
+ kbd_reset_keyboard(s);
+ s->scan_enabled = 0;
+ kbd_queue(s, KBD_REPLY_ACK, 0);
+ break;
+ case KBD_CMD_RESET_ENABLE:
+ kbd_reset_keyboard(s);
+ s->scan_enabled = 1;
+ kbd_queue(s, KBD_REPLY_ACK, 0);
+ break;
+ case KBD_CMD_RESET:
+ kbd_reset_keyboard(s);
+ kbd_queue(s, KBD_REPLY_ACK, 0);
+ kbd_queue(s, KBD_REPLY_POR, 0);
+ break;
+ default:
+ kbd_queue(s, KBD_REPLY_ACK, 0);
+ break;
+ }
+ break;
+ case KBD_CMD_SET_LEDS:
+ kbd_queue(s, KBD_REPLY_ACK, 0);
+ s->kbd_write_cmd = -1;
+ break;
+ case KBD_CMD_SET_RATE:
+ kbd_queue(s, KBD_REPLY_ACK, 0);
+ s->kbd_write_cmd = -1;
+ break;
+ }
+}
+
+static void kbd_mouse_send_packet(KBDState *s)
+{
+ unsigned int b;
+ int dx1, dy1, dz1;
+
+ dx1 = s->mouse_dx;
+ dy1 = s->mouse_dy;
+ dz1 = s->mouse_dz;
+ if (s->touchpad.absolute)
+ {
+ int dz2, dleftnright, dg, df;
+ if (dx1 > 6143)
+ dx1 = 6143;
+ else if (dx1 < 0)
+ dx1 = 0;
+ if (dy1 > 6143)
+ dy1 = 6143;
+ else if (dy1 < 0)
+ dy1 = 0;
+ dz2 = 80; /* normal finger pressure */
+ dg = 0; /* guesture not supported */
+ df = 0; /* finger not supported */
+ dleftnright = (s->mouse_buttons & 0x07);
+ /*
+ X: 13 bits --return absolute x ord
+ Y: 13 bits --return absolute y ord
+ Z: 8 bits --return constant 80 since we don't know how hard the user
+ is pressing on the mouse button ;) 80 is the default for pen
+ pressure, as touchpads cant sense what pressure a pen makes.
+ W: 4 bits --return 0, we don't support finger width (should we?)
+ left: 1 bit --is left button pressed
+ right: 1 bit --is right button pressed
+ guesture: 1 bit --we dont support, return 0
+ finger: 1 bit --ditto
+ total: 42 bits in 6 bytes
+ note that Synaptics drivers ignore the finger and guesture bits and
+ consider them redundant
+ */
+ /*
+ note: the packet setup is different when Wmode = 1, but
+ this doesn't apply since we don't support Wmode capability
+ format of packet is as follows:
+ */
+ // 1 0 finger reserved 0 gesture right left
+ kbd_queue(s, (0x80 | (df ? 0x20 : 0) | (dg ? 0x04 : 0) | dleftnright), 1);
+ kbd_queue(s, ((dy1 & 0xF) * 256) + (dx1 & 0xF), 1);
+ kbd_queue(s, 80, 1); //byte 3
+ // 1 1 y-12 x-12 0 gesture right left
+ kbd_queue(s, (0xC0 | ((dy1 & 1000) ? 0x20 : 0) | ((dx1 & 1000) ? 0x10 : 0) | (dg ? 0x04 : 0) | dleftnright), 1);
+ kbd_queue(s, dx1 & 0xFF, 1);
+ kbd_queue(s, dy1 & 0xFF, 1);
+ return;
+ }
+ /* XXX: increase range to 8 bits ? */
+ if (dx1 > 127)
+ dx1 = 127;
+ else if (dx1 < -127)
+ dx1 = -127;
+ if (dy1 > 127)
+ dy1 = 127;
+ else if (dy1 < -127)
+ dy1 = -127;
+ b = 0x08 | ((dx1 < 0) << 4) | ((dy1 < 0) << 5) | (s->mouse_buttons & 0x07);
+ kbd_queue(s, b, 1);
+ kbd_queue(s, dx1 & 0xff, 1);
+ kbd_queue(s, dy1 & 0xff, 1);
+ /* extra byte for IMPS/2 or IMEX */
+ switch(s->mouse_type) {
+ default:
+ break;
+ case 3:
+ if (dz1 > 127)
+ dz1 = 127;
+ else if (dz1 < -127)
+ dz1 = -127;
+ kbd_queue(s, dz1 & 0xff, 1);
+ break;
+ case 4:
+ if (dz1 > 7)
+ dz1 = 7;
+ else if (dz1 < -7)
+ dz1 = -7;
+ b = (dz1 & 0x0f) | ((s->mouse_buttons & 0x18) << 1);
+ kbd_queue(s, b, 1);
+ break;
+ }
+
+ /* update deltas */
+ s->mouse_dx -= dx1;
+ s->mouse_dy -= dy1;
+ s->mouse_dz -= dz1;
+}
+
+static void pc_kbd_mouse_event(void *opaque,
+ int dx, int dy, int dz, int buttons_state)
+{
+ KBDState *s = opaque;
+
+ /* check if deltas are recorded when disabled */
+ if (!(s->mouse_status & MOUSE_STATUS_ENABLED))
+ return;
+
+ s->mouse_dx += dx;
+ s->mouse_dy -= dy;
+ s->mouse_dz += dz;
+ /* XXX: SDL sometimes generates nul events: we delete them */
+ if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0 &&
+ s->mouse_buttons == buttons_state)
+ return;
+ s->mouse_buttons = buttons_state;
+
+ if (!(s->mouse_status & MOUSE_STATUS_REMOTE) &&
+ (s->queue.count < (KBD_QUEUE_SIZE - 16))) {
+ for(;;) {
+ /* if not remote, send event. Multiple events are sent if
+ too big deltas */
+ kbd_mouse_send_packet(s);
+ if (s->mouse_dx == 0 && s->mouse_dy == 0 && s->mouse_dz == 0)
+ break;
+ }
+ }
+}
+
+static void kbd_write_mouse(KBDState *s, int val)
+{
+/* variables needed to store synaptics command info */
+static int rr = 0, ss = 0, tt = 0, uu = 0, res_count = 0, last_com = 0;
+int spare;
+#ifdef DEBUG_MOUSE
+ printf("kbd: write mouse 0x%02x\n", val);
+#endif
+ switch(s->mouse_write_cmd) {
+ default:
+ case -1:
+ /* mouse command */
+ if (s->mouse_wrap) {
+ if (val == AUX_RESET_WRAP) {
+ s->mouse_wrap = 0;
+ kbd_queue(s, AUX_ACK, 1);
+ return;
+ } else if (val != AUX_RESET) {
+ kbd_queue(s, val, 1);
+ return;
+ }
+ }
+ last_com = val;
+ switch(val) {
+ case AUX_SET_SCALE11:
+ s->mouse_status &= ~MOUSE_STATUS_SCALE21;
+ kbd_queue(s, AUX_ACK, 1);
+ break;
+ case AUX_SET_SCALE21:
+ s->mouse_status |= MOUSE_STATUS_SCALE21;
+ kbd_queue(s, AUX_ACK, 1);
+ break;
+ case AUX_SET_STREAM:
+ s->mouse_status &= ~MOUSE_STATUS_REMOTE;
+ kbd_queue(s, AUX_ACK, 1);
+ break;
+ case AUX_SET_WRAP:
+ s->mouse_wrap = 1;
+ kbd_queue(s, AUX_ACK, 1);
+ break;
+ case AUX_SET_REMOTE:
+ s->mouse_status |= MOUSE_STATUS_REMOTE;
+ kbd_queue(s, AUX_ACK, 1);
+ break;
+ case AUX_GET_TYPE:
+ kbd_queue(s, AUX_ACK, 1);
+ kbd_queue(s, s->mouse_type, 1);
+ break;
+ case AUX_SET_RES:
+ case AUX_SET_SAMPLE:
+ s->mouse_write_cmd = val;
+ kbd_queue(s, AUX_ACK, 1);
+ break;
+ case AUX_GET_SCALE:
+ if (res_count == 4)
+ {
+ /* time for the special stuff */
+ kbd_queue(s, AUX_ACK, 1);
+ /* below is how we get the real synaptic command */
+ val = (rr*64) + (ss*16) + (tt*4) + uu;
+ switch(val)
+ {
+ /* id touchpad */
+ case 0x00:
+ /* info Minor */
+ kbd_queue(s, 0x00, 1);
+ /* special verification byte */
+ kbd_queue(s, 0x47, 1);
+ /* info Major * 0x10 + Info ModelCode*/
+ kbd_queue(s, 4 * 0x10 + 0, 1);
+ break;
+ /* read touchpad modes */
+ case 0x01:
+ /* special verification byte */
+ kbd_queue(s, 0x3B, 1);
+ /* mode */
+ /*
+ bit 7 - absolute or relative position
+ bit 6 - 0 for 40 packets/sec, 1 for 80 pack/sec
+ bit 3 - 1 for sleep mode, 0 for normal
+ bit 2 - 1 to detect tap/drag, 0 to disable
+ bit 1 - packet size, only valid for serial protocol
+ bit 0 - 0 for normal packets, 1 for enhanced packets
+ (absolute mode packets which have finger width)
+ */
+ if (s->touchpad.absolute && s->touchpad.high)
+ {
+ spare = 0xC0;
+ }
+ else if (s->touchpad.absolute)
+ {
+ spare = 0x80;
+ }
+ else if (s->touchpad.high)
+ {
+ spare = 0x40;
+ }
+ else
+ {
+ spare = 0x00;
+ }
+ kbd_queue(s, spare, 1);
+ /* special verification byte */
+ kbd_queue(s, 0x47, 1);
+ break;
+ /* read touchpad capabilites */
+ case 0x02:
+ /* extended capability first 8 bits */
+ kbd_queue(s, 0x00, 1);
+ /* special verification byte */
+ kbd_queue(s, 0x47, 1);
+ /* extended capability last 8 bits */
+ kbd_queue(s, 0x00, 1);
+ /* basicly, we don't have any capabilites ;0 */
+ break;
+ /* read model id */
+ case 0x03:
+ /*
+ bit 23 = 0 (1 for upsidedownpad)
+ bit 22 = 0 (1 for 90 degree rotated pad)
+ bits 21-16 = 1 (standard model)
+ bits 15-9 = ??? (reserved for synaptics use)
+ bit 7 = 1
+ bit 6 = 0 (1 for sensing pens)
+ bit 5 = 1
+ bits 3-0 = 1 (rectangular geometery)
+ */
+ kbd_queue(s, 0xFC, 1);
+ kbd_queue(s, 0x00, 1);
+ kbd_queue(s, 0xF5, 1); //F7 for sensing pens
+ break;
+ /* read serial number prefix */
+ case 0x06:
+ /* strange how they have this query even though
+ no touchpad actually has serial numbers */
+ /* return serial prefix of 0 if we dont have one */
+ kbd_queue(s, 0x00, 1);
+ kbd_queue(s, 0x00, 1);
+ kbd_queue(s, 0x00, 1);
+ break;
+ /* read serial number suffix */
+ case 0x07:
+ /* undefined if we dont have a valid serial prefix */
+ kbd_queue(s, 0x00, 1);
+ kbd_queue(s, 0x00, 1);
+ kbd_queue(s, 0x00, 1);
+ break;
+ /* read resolutions */
+ case 0x08:
+ /* going to go with infoSensor = 1 (Standard model) here */
+ /* absolute X in abolute units per mm */
+ kbd_queue(s, 85, 1);
+ /* undefined but first bit 7 will be set to 1...
+ hell I'm going to set them all to 1 */
+ kbd_queue(s, 0xFF, 1);
+ /* absolute Y in abolute units per mm */
+ kbd_queue(s, 94, 1);
+ break;
+ default:
+ /* invalid commands return undefined data */
+ kbd_queue(s, 0x00, 1);
+ kbd_queue(s, 0x00, 1);
+ kbd_queue(s, 0x00, 1);
+ break;
+ }
+ }
+ else
+ {
+ /* not a special command, just do the regular stuff */
+ kbd_queue(s, AUX_ACK, 1);
+ kbd_queue(s, s->mouse_status, 1);
+ kbd_queue(s, s->mouse_resolution, 1);
+ kbd_queue(s, s->mouse_sample_rate, 1);
+ }
+ break;
+ case AUX_POLL:
+ kbd_queue(s, AUX_ACK, 1);
+ kbd_mouse_send_packet(s);
+ break;
+ case AUX_ENABLE_DEV:
+ s->mouse_status |= MOUSE_STATUS_ENABLED;
+ kbd_queue(s, AUX_ACK, 1);
+ break;
+ case AUX_DISABLE_DEV:
+ s->mouse_status &= ~MOUSE_STATUS_ENABLED;
+ kbd_queue(s, AUX_ACK, 1);
+ break;
+ case AUX_SET_DEFAULT:
+ s->mouse_sample_rate = 100;
+ s->mouse_resolution = 2;
+ s->mouse_status = 0;
+ s->touchpad.absolute = 0;
+ kbd_queue(s, AUX_ACK, 1);
+ break;
+ case AUX_RESET:
+ s->mouse_sample_rate = 100;
+ s->mouse_resolution = 2;
+ s->mouse_status = 0;
+ s->touchpad.absolute = 0;
+ kbd_queue(s, AUX_ACK, 1);
+ kbd_queue(s, 0xaa, 1);
+ kbd_queue(s, s->mouse_type, 1);
+ break;
+ default:
+ break;
+ }
+ break;
+ case AUX_SET_SAMPLE:
+ if (res_count == 4 && val == 0x14)
+ {
+ /* time for the special stuff */
+ /* below is how we get the real synaptic command */
+ val = (rr*64) + (ss*16) + (tt*4) + uu;
+ /* TODO: set the mode byte */
+ } else
+ s->mouse_sample_rate = val;
+#if 0
+ /* detect IMPS/2 or IMEX */
+ switch(s->mouse_detect_state) {
+ default:
+ case 0:
+ if (val == 200)
+ s->mouse_detect_state = 1;
+ break;
+ case 1:
+ if (val == 100)
+ s->mouse_detect_state = 2;
+ else if (val == 200)
+ s->mouse_detect_state = 3;
+ else
+ s->mouse_detect_state = 0;
+ break;
+ case 2:
+ if (val == 80)
+ s->mouse_type = 3; /* IMPS/2 */
+ s->mouse_detect_state = 0;
+ break;
+ case 3:
+ if (val == 80)
+ s->mouse_type = 4; /* IMEX */
+ s->mouse_detect_state = 0;
+ break;
+ }
+#endif
+ kbd_queue(s, AUX_ACK, 1);
+ s->mouse_write_cmd = -1;
+ break;
+ case AUX_SET_RES:
+ if (last_com != AUX_SET_RES)
+ {
+ /* if its not 4 in a row, its not a command */
+ /* FIXME: if we are set 8 of these in a row, or 12, or 16,
+ or etc ... or 4^n commands, then the nth'd mode byte sent might
+ still work. not sure if this is how things are suppose to be
+ or not. */
+ res_count = 0;
+ }
+ res_count++;
+ if (res_count > 4) res_count = 4;
+ switch(res_count)
+ /* we need to save the val in the right spots to get the
+ real command later */
+ {
+ case 1:
+ break;
+ rr = val;
+ case 2:
+ ss = val;
+ break;
+ case 3:
+ tt = val;
+ break;
+ case 4:
+ uu = val;
+ break;
+ }
+ s->mouse_resolution = val;
+ kbd_queue(s, AUX_ACK, 1);
+ s->mouse_write_cmd = -1;
+ break;
+ }
+}
+
+void kbd_write_data(void *opaque, uint32_t addr, uint32_t val)
+{
+ KBDState *s = opaque;
+
+#ifdef DEBUG_KBD
+ printf("kbd: write data=0x%02x\n", val);
+#endif
+
+ switch(s->write_cmd) {
+ case 0:
+ kbd_write_keyboard(s, val);
+ break;
+ case KBD_CCMD_WRITE_MODE:
+ s->mode = val;
+ kbd_update_irq(s);
+ break;
+ case KBD_CCMD_WRITE_OBUF:
+ kbd_queue(s, val, 0);
+ break;
+ case KBD_CCMD_WRITE_AUX_OBUF:
+ kbd_queue(s, val, 1);
+ break;
+ case KBD_CCMD_WRITE_OUTPORT:
+#ifdef TARGET_I386
+ cpu_x86_set_a20(cpu_single_env, (val >> 1) & 1);
+#endif
+ if (!(val & 1)) {
+ qemu_system_reset_request();
+ }
+ break;
+ case KBD_CCMD_WRITE_MOUSE:
+ kbd_write_mouse(s, val);
+ break;
+ default:
+ break;
+ }
+ s->write_cmd = 0;
+}
+
+static void kbd_reset(void *opaque)
+{
+ KBDState *s = opaque;
+ KBDQueue *q;
+
+ s->kbd_write_cmd = -1;
+ s->mouse_write_cmd = -1;
+ s->mode = KBD_MODE_KBD_INT | KBD_MODE_MOUSE_INT | KBD_MODE_KCC;
+ s->status = KBD_STAT_CMD | KBD_STAT_UNLOCKED;
+ q = &s->queue;
+ q->rptr = 0;
+ q->wptr = 0;
+ q->count = 0;
+}
+
+static void kbd_save(QEMUFile* f, void* opaque)
+{
+ KBDState *s = (KBDState*)opaque;
+
+ qemu_put_8s(f, &s->write_cmd);
+ qemu_put_8s(f, &s->status);
+ qemu_put_8s(f, &s->mode);
+ qemu_put_be32s(f, &s->kbd_write_cmd);
+ qemu_put_be32s(f, &s->scan_enabled);
+ qemu_put_be32s(f, &s->mouse_write_cmd);
+ qemu_put_8s(f, &s->mouse_status);
+ qemu_put_8s(f, &s->mouse_resolution);
+ qemu_put_8s(f, &s->mouse_sample_rate);
+ qemu_put_8s(f, &s->mouse_wrap);
+ qemu_put_8s(f, &s->mouse_type);
+ qemu_put_8s(f, &s->mouse_detect_state);
+ qemu_put_be32s(f, &s->mouse_dx);
+ qemu_put_be32s(f, &s->mouse_dy);
+ qemu_put_be32s(f, &s->mouse_dz);
+ qemu_put_8s(f, &s->mouse_buttons);
+ qemu_put_be32s(f, &s->touchpad.absolute);
+ qemu_put_be32s(f, &s->touchpad.high);
+}
+
+static int kbd_load(QEMUFile* f, void* opaque, int version_id)
+{
+ KBDState *s = (KBDState*)opaque;
+
+ if (version_id != 2)
+ return -EINVAL;
+ qemu_get_8s(f, &s->write_cmd);
+ qemu_get_8s(f, &s->status);
+ qemu_get_8s(f, &s->mode);
+ qemu_get_be32s(f, &s->kbd_write_cmd);
+ qemu_get_be32s(f, &s->scan_enabled);
+ qemu_get_be32s(f, &s->mouse_write_cmd);
+ qemu_get_8s(f, &s->mouse_status);
+ qemu_get_8s(f, &s->mouse_resolution);
+ qemu_get_8s(f, &s->mouse_sample_rate);
+ qemu_get_8s(f, &s->mouse_wrap);
+ qemu_get_8s(f, &s->mouse_type);
+ qemu_get_8s(f, &s->mouse_detect_state);
+ qemu_get_be32s(f, &s->mouse_dx);
+ qemu_get_be32s(f, &s->mouse_dy);
+ qemu_get_be32s(f, &s->mouse_dz);
+ qemu_get_8s(f, &s->mouse_buttons);
+ qemu_get_be32s(f, &s->touchpad.absolute);
+ qemu_get_be32s(f, &s->touchpad.high);
+ return 0;
+}
+
+void kbd_init(void)
+{
+ KBDState *s = &kbd_state;
+
+ kbd_reset(s);
+ register_savevm("pckbd", 0, 2, kbd_save, kbd_load, s);
+ register_ioport_read(0x60, 1, 1, kbd_read_data, s);
+ register_ioport_write(0x60, 1, 1, kbd_write_data, s);
+ register_ioport_read(0x64, 1, 1, kbd_read_status, s);
+ register_ioport_write(0x64, 1, 1, kbd_write_command, s);
+
+ qemu_add_kbd_event_handler(pc_kbd_put_keycode, s);
+ qemu_add_mouse_event_handler(pc_kbd_mouse_event, s);
+ qemu_register_reset(kbd_reset, s);
+}
--- /dev/null
+/*
+ * QEMU generic PPC hardware System Emulator
+ *
+ * Copyright (c) 2003-2004 Jocelyn Mayer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+#include "m48t59.h"
+
+/*****************************************************************************/
+/* PPC time base and decrementer emulation */
+//#define DEBUG_TB
+
+struct ppc_tb_t {
+ /* Time base management */
+ int64_t tb_offset; /* Compensation */
+ uint32_t tb_freq; /* TB frequency */
+ /* Decrementer management */
+ uint64_t decr_next; /* Tick for next decr interrupt */
+ struct QEMUTimer *decr_timer;
+};
+
+static inline uint64_t cpu_ppc_get_tb (ppc_tb_t *tb_env)
+{
+ /* TB time in tb periods */
+ return muldiv64(qemu_get_clock(vm_clock) + tb_env->tb_offset,
+ tb_env->tb_freq, ticks_per_sec);
+}
+
+uint32_t cpu_ppc_load_tbl (CPUState *env)
+{
+ ppc_tb_t *tb_env = env->tb_env;
+ uint64_t tb;
+
+ tb = cpu_ppc_get_tb(tb_env);
+#ifdef DEBUG_TB
+ {
+ static int last_time;
+ int now;
+ now = time(NULL);
+ if (last_time != now) {
+ last_time = now;
+ printf("%s: tb=0x%016lx %d %08lx\n",
+ __func__, tb, now, tb_env->tb_offset);
+ }
+ }
+#endif
+
+ return tb & 0xFFFFFFFF;
+}
+
+uint32_t cpu_ppc_load_tbu (CPUState *env)
+{
+ ppc_tb_t *tb_env = env->tb_env;
+ uint64_t tb;
+
+ tb = cpu_ppc_get_tb(tb_env);
+#ifdef DEBUG_TB
+ printf("%s: tb=0x%016lx\n", __func__, tb);
+#endif
+ return tb >> 32;
+}
+
+static void cpu_ppc_store_tb (ppc_tb_t *tb_env, uint64_t value)
+{
+ tb_env->tb_offset = muldiv64(value, ticks_per_sec, tb_env->tb_freq)
+ - qemu_get_clock(vm_clock);
+#ifdef DEBUG_TB
+ printf("%s: tb=0x%016lx offset=%08x\n", __func__, value);
+#endif
+}
+
+void cpu_ppc_store_tbu (CPUState *env, uint32_t value)
+{
+ ppc_tb_t *tb_env = env->tb_env;
+
+ cpu_ppc_store_tb(tb_env,
+ ((uint64_t)value << 32) | cpu_ppc_load_tbl(env));
+}
+
+void cpu_ppc_store_tbl (CPUState *env, uint32_t value)
+{
+ ppc_tb_t *tb_env = env->tb_env;
+
+ cpu_ppc_store_tb(tb_env,
+ ((uint64_t)cpu_ppc_load_tbu(env) << 32) | value);
+}
+
+uint32_t cpu_ppc_load_decr (CPUState *env)
+{
+ ppc_tb_t *tb_env = env->tb_env;
+ uint32_t decr;
+
+ decr = muldiv64(tb_env->decr_next - qemu_get_clock(vm_clock),
+ tb_env->tb_freq, ticks_per_sec);
+#if defined(DEBUG_TB)
+ printf("%s: 0x%08x\n", __func__, decr);
+#endif
+
+ return decr;
+}
+
+/* When decrementer expires,
+ * all we need to do is generate or queue a CPU exception
+ */
+static inline void cpu_ppc_decr_excp (CPUState *env)
+{
+ /* Raise it */
+#ifdef DEBUG_TB
+ printf("raise decrementer exception\n");
+#endif
+ cpu_interrupt(env, CPU_INTERRUPT_TIMER);
+}
+
+static void _cpu_ppc_store_decr (CPUState *env, uint32_t decr,
+ uint32_t value, int is_excp)
+{
+ ppc_tb_t *tb_env = env->tb_env;
+ uint64_t now, next;
+
+#ifdef DEBUG_TB
+ printf("%s: 0x%08x => 0x%08x\n", __func__, decr, value);
+#endif
+ now = qemu_get_clock(vm_clock);
+ next = now + muldiv64(value, ticks_per_sec, tb_env->tb_freq);
+ if (is_excp)
+ next += tb_env->decr_next - now;
+ if (next == now)
+ next++;
+ tb_env->decr_next = next;
+ /* Adjust timer */
+ qemu_mod_timer(tb_env->decr_timer, next);
+ /* If we set a negative value and the decrementer was positive,
+ * raise an exception.
+ */
+ if ((value & 0x80000000) && !(decr & 0x80000000))
+ cpu_ppc_decr_excp(env);
+}
+
+void cpu_ppc_store_decr (CPUState *env, uint32_t value)
+{
+ _cpu_ppc_store_decr(env, cpu_ppc_load_decr(env), value, 0);
+}
+
+static void cpu_ppc_decr_cb (void *opaque)
+{
+ _cpu_ppc_store_decr(opaque, 0x00000000, 0xFFFFFFFF, 1);
+}
+
+/* Set up (once) timebase frequency (in Hz) */
+ppc_tb_t *cpu_ppc_tb_init (CPUState *env, uint32_t freq)
+{
+ ppc_tb_t *tb_env;
+
+ tb_env = qemu_mallocz(sizeof(ppc_tb_t));
+ if (tb_env == NULL)
+ return NULL;
+ env->tb_env = tb_env;
+ if (tb_env->tb_freq == 0 || 1) {
+ tb_env->tb_freq = freq;
+ /* Create new timer */
+ tb_env->decr_timer =
+ qemu_new_timer(vm_clock, &cpu_ppc_decr_cb, env);
+ /* There is a bug in 2.4 kernels:
+ * if a decrementer exception is pending when it enables msr_ee,
+ * it's not ready to handle it...
+ */
+ _cpu_ppc_store_decr(env, 0xFFFFFFFF, 0xFFFFFFFF, 0);
+ }
+
+ return tb_env;
+}
+
+#if 0
+/*****************************************************************************/
+/* Handle system reset (for now, just stop emulation) */
+void cpu_ppc_reset (CPUState *env)
+{
+ printf("Reset asked... Stop emulation\n");
+ abort();
+}
+#endif
+
+static void PPC_io_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+ cpu_outb(NULL, addr & 0xffff, value);
+}
+
+static uint32_t PPC_io_readb (void *opaque, target_phys_addr_t addr)
+{
+ uint32_t ret = cpu_inb(NULL, addr & 0xffff);
+ return ret;
+}
+
+static void PPC_io_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+#ifdef TARGET_WORDS_BIGENDIAN
+ value = bswap16(value);
+#endif
+ cpu_outw(NULL, addr & 0xffff, value);
+}
+
+static uint32_t PPC_io_readw (void *opaque, target_phys_addr_t addr)
+{
+ uint32_t ret = cpu_inw(NULL, addr & 0xffff);
+#ifdef TARGET_WORDS_BIGENDIAN
+ ret = bswap16(ret);
+#endif
+ return ret;
+}
+
+static void PPC_io_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+#ifdef TARGET_WORDS_BIGENDIAN
+ value = bswap32(value);
+#endif
+ cpu_outl(NULL, addr & 0xffff, value);
+}
+
+static uint32_t PPC_io_readl (void *opaque, target_phys_addr_t addr)
+{
+ uint32_t ret = cpu_inl(NULL, addr & 0xffff);
+
+#ifdef TARGET_WORDS_BIGENDIAN
+ ret = bswap32(ret);
+#endif
+ return ret;
+}
+
+CPUWriteMemoryFunc *PPC_io_write[] = {
+ &PPC_io_writeb,
+ &PPC_io_writew,
+ &PPC_io_writel,
+};
+
+CPUReadMemoryFunc *PPC_io_read[] = {
+ &PPC_io_readb,
+ &PPC_io_readw,
+ &PPC_io_readl,
+};
+
+/*****************************************************************************/
+/* Debug port */
+void PPC_debug_write (void *opaque, uint32_t addr, uint32_t val)
+{
+ addr &= 0xF;
+ switch (addr) {
+ case 0:
+ printf("%c", val);
+ break;
+ case 1:
+ printf("\n");
+ fflush(stdout);
+ break;
+ case 2:
+ printf("Set loglevel to %04x\n", val);
+ cpu_set_log(val | 0x100);
+ break;
+ }
+}
+
+/*****************************************************************************/
+/* NVRAM helpers */
+void NVRAM_set_byte (m48t59_t *nvram, uint32_t addr, uint8_t value)
+{
+ m48t59_set_addr(nvram, addr);
+ m48t59_write(nvram, value);
+}
+
+uint8_t NVRAM_get_byte (m48t59_t *nvram, uint32_t addr)
+{
+ m48t59_set_addr(nvram, addr);
+ return m48t59_read(nvram);
+}
+
+void NVRAM_set_word (m48t59_t *nvram, uint32_t addr, uint16_t value)
+{
+ m48t59_set_addr(nvram, addr);
+ m48t59_write(nvram, value >> 8);
+ m48t59_set_addr(nvram, addr + 1);
+ m48t59_write(nvram, value & 0xFF);
+}
+
+uint16_t NVRAM_get_word (m48t59_t *nvram, uint32_t addr)
+{
+ uint16_t tmp;
+
+ m48t59_set_addr(nvram, addr);
+ tmp = m48t59_read(nvram) << 8;
+ m48t59_set_addr(nvram, addr + 1);
+ tmp |= m48t59_read(nvram);
+
+ return tmp;
+}
+
+void NVRAM_set_lword (m48t59_t *nvram, uint32_t addr, uint32_t value)
+{
+ m48t59_set_addr(nvram, addr);
+ m48t59_write(nvram, value >> 24);
+ m48t59_set_addr(nvram, addr + 1);
+ m48t59_write(nvram, (value >> 16) & 0xFF);
+ m48t59_set_addr(nvram, addr + 2);
+ m48t59_write(nvram, (value >> 8) & 0xFF);
+ m48t59_set_addr(nvram, addr + 3);
+ m48t59_write(nvram, value & 0xFF);
+}
+
+uint32_t NVRAM_get_lword (m48t59_t *nvram, uint32_t addr)
+{
+ uint32_t tmp;
+
+ m48t59_set_addr(nvram, addr);
+ tmp = m48t59_read(nvram) << 24;
+ m48t59_set_addr(nvram, addr + 1);
+ tmp |= m48t59_read(nvram) << 16;
+ m48t59_set_addr(nvram, addr + 2);
+ tmp |= m48t59_read(nvram) << 8;
+ m48t59_set_addr(nvram, addr + 3);
+ tmp |= m48t59_read(nvram);
+
+ return tmp;
+}
+
+void NVRAM_set_string (m48t59_t *nvram, uint32_t addr,
+ const unsigned char *str, uint32_t max)
+{
+ int i;
+
+ for (i = 0; i < max && str[i] != '\0'; i++) {
+ m48t59_set_addr(nvram, addr + i);
+ m48t59_write(nvram, str[i]);
+ }
+ m48t59_set_addr(nvram, addr + max - 1);
+ m48t59_write(nvram, '\0');
+}
+
+int NVRAM_get_string (m48t59_t *nvram, uint8_t *dst, uint16_t addr, int max)
+{
+ int i;
+
+ memset(dst, 0, max);
+ for (i = 0; i < max; i++) {
+ dst[i] = NVRAM_get_byte(nvram, addr + i);
+ if (dst[i] == '\0')
+ break;
+ }
+
+ return i;
+}
+
+static uint16_t NVRAM_crc_update (uint16_t prev, uint16_t value)
+{
+ uint16_t tmp;
+ uint16_t pd, pd1, pd2;
+
+ tmp = prev >> 8;
+ pd = prev ^ value;
+ pd1 = pd & 0x000F;
+ pd2 = ((pd >> 4) & 0x000F) ^ pd1;
+ tmp ^= (pd1 << 3) | (pd1 << 8);
+ tmp ^= pd2 | (pd2 << 7) | (pd2 << 12);
+
+ return tmp;
+}
+
+uint16_t NVRAM_compute_crc (m48t59_t *nvram, uint32_t start, uint32_t count)
+{
+ uint32_t i;
+ uint16_t crc = 0xFFFF;
+ int odd;
+
+ odd = count & 1;
+ count &= ~1;
+ for (i = 0; i != count; i++) {
+ crc = NVRAM_crc_update(crc, NVRAM_get_word(nvram, start + i));
+ }
+ if (odd) {
+ crc = NVRAM_crc_update(crc, NVRAM_get_byte(nvram, start + i) << 8);
+ }
+
+ return crc;
+}
+
+#define CMDLINE_ADDR 0x017ff000
+
+int PPC_NVRAM_set_params (m48t59_t *nvram, uint16_t NVRAM_size,
+ const unsigned char *arch,
+ uint32_t RAM_size, int boot_device,
+ uint32_t kernel_image, uint32_t kernel_size,
+ const char *cmdline,
+ uint32_t initrd_image, uint32_t initrd_size,
+ uint32_t NVRAM_image,
+ int width, int height, int depth)
+{
+ uint16_t crc;
+
+ /* Set parameters for Open Hack'Ware BIOS */
+ NVRAM_set_string(nvram, 0x00, "QEMU_BIOS", 16);
+ NVRAM_set_lword(nvram, 0x10, 0x00000002); /* structure v2 */
+ NVRAM_set_word(nvram, 0x14, NVRAM_size);
+ NVRAM_set_string(nvram, 0x20, arch, 16);
+ NVRAM_set_lword(nvram, 0x30, RAM_size);
+ NVRAM_set_byte(nvram, 0x34, boot_device);
+ NVRAM_set_lword(nvram, 0x38, kernel_image);
+ NVRAM_set_lword(nvram, 0x3C, kernel_size);
+ if (cmdline) {
+ /* XXX: put the cmdline in NVRAM too ? */
+ strcpy(phys_ram_base + CMDLINE_ADDR, cmdline);
+ NVRAM_set_lword(nvram, 0x40, CMDLINE_ADDR);
+ NVRAM_set_lword(nvram, 0x44, strlen(cmdline));
+ } else {
+ NVRAM_set_lword(nvram, 0x40, 0);
+ NVRAM_set_lword(nvram, 0x44, 0);
+ }
+ NVRAM_set_lword(nvram, 0x48, initrd_image);
+ NVRAM_set_lword(nvram, 0x4C, initrd_size);
+ NVRAM_set_lword(nvram, 0x50, NVRAM_image);
+
+ NVRAM_set_word(nvram, 0x54, width);
+ NVRAM_set_word(nvram, 0x56, height);
+ NVRAM_set_word(nvram, 0x58, depth);
+ crc = NVRAM_compute_crc(nvram, 0x00, 0xF8);
+ NVRAM_set_word(nvram, 0xFC, crc);
+
+ return 0;
+ }
+
+/*****************************************************************************/
+void ppc_init (int ram_size, int vga_ram_size, int boot_device,
+ DisplayState *ds, const char **fd_filename, int snapshot,
+ const char *kernel_filename, const char *kernel_cmdline,
+ const char *initrd_filename)
+{
+ if (prep_enabled) {
+ ppc_prep_init(ram_size, vga_ram_size, boot_device, ds, fd_filename,
+ snapshot, kernel_filename, kernel_cmdline,
+ initrd_filename);
+ } else {
+ ppc_chrp_init(ram_size, vga_ram_size, boot_device, ds, fd_filename,
+ snapshot, kernel_filename, kernel_cmdline,
+ initrd_filename);
+ }
+ /* Special port to get debug messages from Open-Firmware */
+ register_ioport_write(0x0F00, 4, 1, &PPC_debug_write, NULL);
+}
--- /dev/null
+/*
+ * QEMU PPC CHRP/PMAC hardware System Emulator
+ *
+ * Copyright (c) 2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+
+#define BIOS_FILENAME "ppc_rom.bin"
+#define NVRAM_SIZE 0x2000
+
+#define KERNEL_LOAD_ADDR 0x01000000
+#define INITRD_LOAD_ADDR 0x01800000
+
+/* MacIO devices (mapped inside the MacIO address space): CUDA, DBDMA,
+ NVRAM (not implemented). */
+
+static int dbdma_mem_index;
+static int cuda_mem_index;
+static int ide0_mem_index;
+static int ide1_mem_index;
+static int openpic_mem_index;
+
+/* DBDMA: currently no op - should suffice right now */
+
+static void dbdma_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+ printf("%s: 0x%08x <= 0x%08x\n", __func__, addr, value);
+}
+
+static void dbdma_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+}
+
+static void dbdma_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+}
+
+static uint32_t dbdma_readb (void *opaque, target_phys_addr_t addr)
+{
+ printf("%s: 0x%08x => 0x00000000\n", __func__, addr);
+ return 0;
+}
+
+static uint32_t dbdma_readw (void *opaque, target_phys_addr_t addr)
+{
+ return 0;
+}
+
+static uint32_t dbdma_readl (void *opaque, target_phys_addr_t addr)
+{
+ return 0;
+}
+
+static CPUWriteMemoryFunc *dbdma_write[] = {
+ &dbdma_writeb,
+ &dbdma_writew,
+ &dbdma_writel,
+};
+
+static CPUReadMemoryFunc *dbdma_read[] = {
+ &dbdma_readb,
+ &dbdma_readw,
+ &dbdma_readl,
+};
+
+static void macio_map(PCIDevice *pci_dev, int region_num,
+ uint32_t addr, uint32_t size, int type)
+{
+ cpu_register_physical_memory(addr + 0x08000, 0x1000, dbdma_mem_index);
+ cpu_register_physical_memory(addr + 0x16000, 0x2000, cuda_mem_index);
+ cpu_register_physical_memory(addr + 0x1f000, 0x1000, ide0_mem_index);
+ cpu_register_physical_memory(addr + 0x20000, 0x1000, ide1_mem_index);
+ cpu_register_physical_memory(addr + 0x40000, 0x40000, openpic_mem_index);
+}
+
+static void macio_init(PCIBus *bus)
+{
+ PCIDevice *d;
+
+ d = pci_register_device(bus, "macio", sizeof(PCIDevice),
+ -1, NULL, NULL);
+ /* Note: this code is strongly inspirated from the corresponding code
+ in PearPC */
+ d->config[0x00] = 0x6b; // vendor_id
+ d->config[0x01] = 0x10;
+ d->config[0x02] = 0x22;
+ d->config[0x03] = 0x00;
+
+ d->config[0x0a] = 0x00; // class_sub = pci2pci
+ d->config[0x0b] = 0xff; // class_base = bridge
+ d->config[0x0e] = 0x00; // header_type
+
+ d->config[0x3d] = 0x01; // interrupt on pin 1
+
+ dbdma_mem_index = cpu_register_io_memory(0, dbdma_read, dbdma_write, NULL);
+
+ pci_register_io_region(d, 0, 0x80000,
+ PCI_ADDRESS_SPACE_MEM, macio_map);
+}
+
+/* PowerPC PREP hardware initialisation */
+void ppc_chrp_init(int ram_size, int vga_ram_size, int boot_device,
+ DisplayState *ds, const char **fd_filename, int snapshot,
+ const char *kernel_filename, const char *kernel_cmdline,
+ const char *initrd_filename)
+{
+ char buf[1024];
+ openpic_t *openpic;
+ m48t59_t *nvram;
+ int PPC_io_memory;
+ int ret, linux_boot, i;
+ unsigned long bios_offset;
+ uint32_t kernel_base, kernel_size, initrd_base, initrd_size;
+ PCIBus *pci_bus;
+
+ linux_boot = (kernel_filename != NULL);
+
+ /* allocate RAM */
+ cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
+
+ /* allocate and load BIOS */
+ bios_offset = ram_size + vga_ram_size;
+ snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
+ ret = load_image(buf, phys_ram_base + bios_offset);
+ if (ret != BIOS_SIZE) {
+ fprintf(stderr, "qemu: could not load PPC PREP bios '%s'\n", buf);
+ exit(1);
+ }
+ cpu_register_physical_memory((uint32_t)(-BIOS_SIZE),
+ BIOS_SIZE, bios_offset | IO_MEM_ROM);
+ cpu_single_env->nip = 0xfffffffc;
+
+ if (linux_boot) {
+ kernel_base = KERNEL_LOAD_ADDR;
+ /* now we can load the kernel */
+ kernel_size = load_image(kernel_filename, phys_ram_base + kernel_base);
+ if (kernel_size < 0) {
+ fprintf(stderr, "qemu: could not load kernel '%s'\n",
+ kernel_filename);
+ exit(1);
+ }
+ /* load initrd */
+ if (initrd_filename) {
+ initrd_base = INITRD_LOAD_ADDR;
+ initrd_size = load_image(initrd_filename,
+ phys_ram_base + initrd_base);
+ if (initrd_size < 0) {
+ fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
+ initrd_filename);
+ exit(1);
+ }
+ } else {
+ initrd_base = 0;
+ initrd_size = 0;
+ }
+ boot_device = 'm';
+ } else {
+ kernel_base = 0;
+ kernel_size = 0;
+ initrd_base = 0;
+ initrd_size = 0;
+ }
+ /* Register CPU as a 74x/75x */
+ cpu_ppc_register(cpu_single_env, 0x00080000);
+ /* Set time-base frequency to 100 Mhz */
+ cpu_ppc_tb_init(cpu_single_env, 100UL * 1000UL * 1000UL);
+
+ isa_mem_base = 0x80000000;
+ pci_bus = pci_pmac_init();
+
+ /* Register 8 MB of ISA IO space */
+ PPC_io_memory = cpu_register_io_memory(0, PPC_io_read, PPC_io_write, NULL);
+ cpu_register_physical_memory(0xF2000000, 0x00800000, PPC_io_memory);
+
+ /* init basic PC hardware */
+ vga_initialize(pci_bus, ds, phys_ram_base + ram_size, ram_size,
+ vga_ram_size);
+ openpic = openpic_init(NULL, &openpic_mem_index, 1);
+ pci_pmac_set_openpic(pci_bus, openpic);
+
+ /* XXX: suppress that */
+ pic_init();
+
+ /* XXX: use Mac Serial port */
+ serial_init(0x3f8, 4, serial_hds[0]);
+
+ for(i = 0; i < nb_nics; i++) {
+ pci_ne2000_init(pci_bus, &nd_table[i]);
+ }
+
+ ide0_mem_index = pmac_ide_init(&bs_table[0], openpic, 0x13);
+ ide1_mem_index = pmac_ide_init(&bs_table[2], openpic, 0x13);
+
+ /* cuda also initialize ADB */
+ cuda_mem_index = cuda_init(openpic, 0x19);
+
+ adb_kbd_init(&adb_bus);
+ adb_mouse_init(&adb_bus);
+
+ macio_init(pci_bus);
+
+ nvram = m48t59_init(8, 0xFFF04000, 0x0074, NVRAM_SIZE);
+
+ if (graphic_depth != 15 && graphic_depth != 32 && graphic_depth != 8)
+ graphic_depth = 15;
+
+ PPC_NVRAM_set_params(nvram, NVRAM_SIZE, "CHRP", ram_size, boot_device,
+ kernel_base, kernel_size,
+ kernel_cmdline,
+ initrd_base, initrd_size,
+ /* XXX: need an option to load a NVRAM image */
+ 0,
+ graphic_width, graphic_height, graphic_depth);
+ /* No PCI init: the BIOS will do it */
+}
--- /dev/null
+/*
+ * QEMU PPC PREP hardware System Emulator
+ *
+ * Copyright (c) 2003-2004 Jocelyn Mayer
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+
+//#define HARD_DEBUG_PPC_IO
+//#define DEBUG_PPC_IO
+
+#define BIOS_FILENAME "ppc_rom.bin"
+#define KERNEL_LOAD_ADDR 0x01000000
+#define INITRD_LOAD_ADDR 0x01800000
+
+extern int loglevel;
+extern FILE *logfile;
+
+#if defined (HARD_DEBUG_PPC_IO) && !defined (DEBUG_PPC_IO)
+#define DEBUG_PPC_IO
+#endif
+
+#if defined (HARD_DEBUG_PPC_IO)
+#define PPC_IO_DPRINTF(fmt, args...) \
+do { \
+ if (loglevel & CPU_LOG_IOPORT) { \
+ fprintf(logfile, "%s: " fmt, __func__ , ##args); \
+ } else { \
+ printf("%s : " fmt, __func__ , ##args); \
+ } \
+} while (0)
+#elif defined (DEBUG_PPC_IO)
+#define PPC_IO_DPRINTF(fmt, args...) \
+do { \
+ if (loglevel & CPU_LOG_IOPORT) { \
+ fprintf(logfile, "%s: " fmt, __func__ , ##args); \
+ } \
+} while (0)
+#else
+#define PPC_IO_DPRINTF(fmt, args...) do { } while (0)
+#endif
+
+/* Constants for devices init */
+static const int ide_iobase[2] = { 0x1f0, 0x170 };
+static const int ide_iobase2[2] = { 0x3f6, 0x376 };
+static const int ide_irq[2] = { 13, 13 };
+
+#define NE2000_NB_MAX 6
+
+static uint32_t ne2000_io[NE2000_NB_MAX] = { 0x300, 0x320, 0x340, 0x360, 0x280, 0x380 };
+static int ne2000_irq[NE2000_NB_MAX] = { 9, 10, 11, 3, 4, 5 };
+
+//static PITState *pit;
+
+/* ISA IO ports bridge */
+#define PPC_IO_BASE 0x80000000
+
+/* Speaker port 0x61 */
+int speaker_data_on;
+int dummy_refresh_clock;
+
+static void speaker_ioport_write(void *opaque, uint32_t addr, uint32_t val)
+{
+#if 0
+ speaker_data_on = (val >> 1) & 1;
+ pit_set_gate(pit, 2, val & 1);
+#endif
+}
+
+static uint32_t speaker_ioport_read(void *opaque, uint32_t addr)
+{
+#if 0
+ int out;
+ out = pit_get_out(pit, 2, qemu_get_clock(vm_clock));
+ dummy_refresh_clock ^= 1;
+ return (speaker_data_on << 1) | pit_get_gate(pit, 2) | (out << 5) |
+ (dummy_refresh_clock << 4);
+#endif
+ return 0;
+}
+
+/* PCI intack register */
+/* Read-only register (?) */
+static void _PPC_intack_write (void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+ // printf("%s: 0x%08x => 0x%08x\n", __func__, addr, value);
+}
+
+static inline uint32_t _PPC_intack_read (target_phys_addr_t addr)
+{
+ uint32_t retval = 0;
+
+ if (addr == 0xBFFFFFF0)
+ retval = pic_intack_read(NULL);
+ // printf("%s: 0x%08x <= %d\n", __func__, addr, retval);
+
+ return retval;
+}
+
+static uint32_t PPC_intack_readb (void *opaque, target_phys_addr_t addr)
+{
+ return _PPC_intack_read(addr);
+}
+
+static uint32_t PPC_intack_readw (void *opaque, target_phys_addr_t addr)
+{
+#ifdef TARGET_WORDS_BIGENDIAN
+ return bswap16(_PPC_intack_read(addr));
+#else
+ return _PPC_intack_read(addr);
+#endif
+}
+
+static uint32_t PPC_intack_readl (void *opaque, target_phys_addr_t addr)
+{
+#ifdef TARGET_WORDS_BIGENDIAN
+ return bswap32(_PPC_intack_read(addr));
+#else
+ return _PPC_intack_read(addr);
+#endif
+}
+
+static CPUWriteMemoryFunc *PPC_intack_write[] = {
+ &_PPC_intack_write,
+ &_PPC_intack_write,
+ &_PPC_intack_write,
+};
+
+static CPUReadMemoryFunc *PPC_intack_read[] = {
+ &PPC_intack_readb,
+ &PPC_intack_readw,
+ &PPC_intack_readl,
+};
+
+/* PowerPC control and status registers */
+#if 0 // Not used
+static struct {
+ /* IDs */
+ uint32_t veni_devi;
+ uint32_t revi;
+ /* Control and status */
+ uint32_t gcsr;
+ uint32_t xcfr;
+ uint32_t ct32;
+ uint32_t mcsr;
+ /* General purpose registers */
+ uint32_t gprg[6];
+ /* Exceptions */
+ uint32_t feen;
+ uint32_t fest;
+ uint32_t fema;
+ uint32_t fecl;
+ uint32_t eeen;
+ uint32_t eest;
+ uint32_t eecl;
+ uint32_t eeint;
+ uint32_t eemck0;
+ uint32_t eemck1;
+ /* Error diagnostic */
+} XCSR;
+
+static void PPC_XCSR_writeb (void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+ printf("%s: 0x%08lx => 0x%08x\n", __func__, (long)addr, value);
+}
+
+static void PPC_XCSR_writew (void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+#ifdef TARGET_WORDS_BIGENDIAN
+ value = bswap16(value);
+#endif
+ printf("%s: 0x%08lx => 0x%08x\n", __func__, (long)addr, value);
+}
+
+static void PPC_XCSR_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
+{
+#ifdef TARGET_WORDS_BIGENDIAN
+ value = bswap32(value);
+#endif
+ printf("%s: 0x%08lx => 0x%08x\n", __func__, (long)addr, value);
+}
+
+static uint32_t PPC_XCSR_readb (void *opaque, target_phys_addr_t addr)
+{
+ uint32_t retval = 0;
+
+ printf("%s: 0x%08lx <= %d\n", __func__, (long)addr, retval);
+
+ return retval;
+}
+
+static uint32_t PPC_XCSR_readw (void *opaque, target_phys_addr_t addr)
+{
+ uint32_t retval = 0;
+
+ printf("%s: 0x%08lx <= %d\n", __func__, (long)addr, retval);
+#ifdef TARGET_WORDS_BIGENDIAN
+ retval = bswap16(retval);
+#endif
+
+ return retval;
+}
+
+static uint32_t PPC_XCSR_readl (void *opaque, target_phys_addr_t addr)
+{
+ uint32_t retval = 0;
+
+ printf("%s: 0x%08lx <= %d\n", __func__, (long)addr, retval);
+#ifdef TARGET_WORDS_BIGENDIAN
+ retval = bswap32(retval);
+#endif
+
+ return retval;
+}
+
+static CPUWriteMemoryFunc *PPC_XCSR_write[] = {
+ &PPC_XCSR_writeb,
+ &PPC_XCSR_writew,
+ &PPC_XCSR_writel,
+};
+
+static CPUReadMemoryFunc *PPC_XCSR_read[] = {
+ &PPC_XCSR_readb,
+ &PPC_XCSR_readw,
+ &PPC_XCSR_readl,
+};
+#endif
+
+/* Fake super-io ports for PREP platform (Intel 82378ZB) */
+typedef struct sysctrl_t {
+ m48t59_t *nvram;
+ uint8_t state;
+ uint8_t syscontrol;
+ uint8_t fake_io[2];
+} sysctrl_t;
+
+enum {
+ STATE_HARDFILE = 0x01,
+};
+
+static sysctrl_t *sysctrl;
+
+static void PREP_io_write (void *opaque, uint32_t addr, uint32_t val)
+{
+ sysctrl_t *sysctrl = opaque;
+
+ PPC_IO_DPRINTF("0x%08lx => 0x%08x\n", (long)addr - PPC_IO_BASE, val);
+ sysctrl->fake_io[addr - 0x0398] = val;
+}
+
+static uint32_t PREP_io_read (void *opaque, uint32_t addr)
+{
+ sysctrl_t *sysctrl = opaque;
+
+ PPC_IO_DPRINTF("0x%08lx <= 0x%08x\n", (long)addr - PPC_IO_BASE,
+ sysctrl->fake_io[addr - 0x0398]);
+ return sysctrl->fake_io[addr - 0x0398];
+}
+
+static void PREP_io_800_writeb (void *opaque, uint32_t addr, uint32_t val)
+{
+ sysctrl_t *sysctrl = opaque;
+
+ PPC_IO_DPRINTF("0x%08lx => 0x%08x\n", (long)addr - PPC_IO_BASE, val);
+ switch (addr) {
+ case 0x0092:
+ /* Special port 92 */
+ /* Check soft reset asked */
+ if (val & 0x01) {
+ // cpu_interrupt(cpu_single_env, CPU_INTERRUPT_RESET);
+ }
+ /* Check LE mode */
+ if (val & 0x02) {
+ printf("Little Endian mode isn't supported (yet ?)\n");
+ abort();
+ }
+ break;
+ case 0x0800:
+ /* Motorola CPU configuration register : read-only */
+ break;
+ case 0x0802:
+ /* Motorola base module feature register : read-only */
+ break;
+ case 0x0803:
+ /* Motorola base module status register : read-only */
+ break;
+ case 0x0808:
+ /* Hardfile light register */
+ if (val & 1)
+ sysctrl->state |= STATE_HARDFILE;
+ else
+ sysctrl->state &= ~STATE_HARDFILE;
+ break;
+ case 0x0810:
+ /* Password protect 1 register */
+ if (sysctrl->nvram != NULL)
+ m48t59_toggle_lock(sysctrl->nvram, 1);
+ break;
+ case 0x0812:
+ /* Password protect 2 register */
+ if (sysctrl->nvram != NULL)
+ m48t59_toggle_lock(sysctrl->nvram, 2);
+ break;
+ case 0x0814:
+ /* L2 invalidate register */
+ // tlb_flush(cpu_single_env, 1);
+ break;
+ case 0x081C:
+ /* system control register */
+ sysctrl->syscontrol = val & 0x0F;
+ break;
+ case 0x0850:
+ /* I/O map type register */
+ if (!(val & 0x01)) {
+ printf("No support for non-continuous I/O map mode\n");
+ abort();
+ }
+ break;
+ default:
+ printf("ERROR: unaffected IO port write: %04lx => %02x\n",
+ (long)addr, val);
+ break;
+ }
+}
+
+static uint32_t PREP_io_800_readb (void *opaque, uint32_t addr)
+{
+ sysctrl_t *sysctrl = opaque;
+ uint32_t retval = 0xFF;
+
+ switch (addr) {
+ case 0x0092:
+ /* Special port 92 */
+ retval = 0x00;
+ break;
+ case 0x0800:
+ /* Motorola CPU configuration register */
+ retval = 0xEF; /* MPC750 */
+ break;
+ case 0x0802:
+ /* Motorola Base module feature register */
+ retval = 0xAD; /* No ESCC, PMC slot neither ethernet */
+ break;
+ case 0x0803:
+ /* Motorola base module status register */
+ retval = 0xE0; /* Standard MPC750 */
+ break;
+ case 0x080C:
+ /* Equipment present register:
+ * no L2 cache
+ * no upgrade processor
+ * no cards in PCI slots
+ * SCSI fuse is bad
+ */
+ retval = 0x3C;
+ break;
+ case 0x0810:
+ /* Motorola base module extended feature register */
+ retval = 0x39; /* No USB, CF and PCI bridge. NVRAM present */
+ break;
+ case 0x0818:
+ /* Keylock */
+ retval = 0x00;
+ break;
+ case 0x081C:
+ /* system control register
+ * 7 - 6 / 1 - 0: L2 cache enable
+ */
+ retval = sysctrl->syscontrol;
+ break;
+ case 0x0823:
+ /* */
+ retval = 0x03; /* no L2 cache */
+ break;
+ case 0x0850:
+ /* I/O map type register */
+ retval = 0x01;
+ break;
+ default:
+ printf("ERROR: unaffected IO port: %04lx read\n", (long)addr);
+ break;
+ }
+ PPC_IO_DPRINTF("0x%08lx <= 0x%08x\n", (long)addr - PPC_IO_BASE, retval);
+
+ return retval;
+}
+
+extern CPUPPCState *global_env;
+
+#define NVRAM_SIZE 0x2000
+
+/* PowerPC PREP hardware initialisation */
+void ppc_prep_init(int ram_size, int vga_ram_size, int boot_device,
+ DisplayState *ds, const char **fd_filename, int snapshot,
+ const char *kernel_filename, const char *kernel_cmdline,
+ const char *initrd_filename)
+{
+ char buf[1024];
+ m48t59_t *nvram;
+ int PPC_io_memory;
+ int ret, linux_boot, i, nb_nics1;
+ unsigned long bios_offset;
+ uint32_t kernel_base, kernel_size, initrd_base, initrd_size;
+ PCIBus *pci_bus;
+
+ sysctrl = qemu_mallocz(sizeof(sysctrl_t));
+ if (sysctrl == NULL)
+ return;
+
+ linux_boot = (kernel_filename != NULL);
+
+ /* allocate RAM */
+ cpu_register_physical_memory(0, ram_size, IO_MEM_RAM);
+
+ /* allocate and load BIOS */
+ bios_offset = ram_size + vga_ram_size;
+ snprintf(buf, sizeof(buf), "%s/%s", bios_dir, BIOS_FILENAME);
+ ret = load_image(buf, phys_ram_base + bios_offset);
+ if (ret != BIOS_SIZE) {
+ fprintf(stderr, "qemu: could not load PPC PREP bios '%s'\n", buf);
+ exit(1);
+ }
+ cpu_register_physical_memory((uint32_t)(-BIOS_SIZE),
+ BIOS_SIZE, bios_offset | IO_MEM_ROM);
+ cpu_single_env->nip = 0xfffffffc;
+
+ if (linux_boot) {
+ kernel_base = KERNEL_LOAD_ADDR;
+ /* now we can load the kernel */
+ kernel_size = load_image(kernel_filename, phys_ram_base + kernel_base);
+ if (kernel_size < 0) {
+ fprintf(stderr, "qemu: could not load kernel '%s'\n",
+ kernel_filename);
+ exit(1);
+ }
+ /* load initrd */
+ if (initrd_filename) {
+ initrd_base = INITRD_LOAD_ADDR;
+ initrd_size = load_image(initrd_filename,
+ phys_ram_base + initrd_base);
+ if (initrd_size < 0) {
+ fprintf(stderr, "qemu: could not load initial ram disk '%s'\n",
+ initrd_filename);
+ exit(1);
+ }
+ } else {
+ initrd_base = 0;
+ initrd_size = 0;
+ }
+ boot_device = 'm';
+ } else {
+ kernel_base = 0;
+ kernel_size = 0;
+ initrd_base = 0;
+ initrd_size = 0;
+ }
+
+ /* Register CPU as a 74x/75x */
+ cpu_ppc_register(cpu_single_env, 0x00080000);
+ /* Set time-base frequency to 100 Mhz */
+ cpu_ppc_tb_init(cpu_single_env, 100UL * 1000UL * 1000UL);
+
+ isa_mem_base = 0xc0000000;
+ pci_bus = pci_prep_init();
+ /* Register 64 KB of ISA IO space */
+ PPC_io_memory = cpu_register_io_memory(0, PPC_io_read, PPC_io_write, NULL);
+ cpu_register_physical_memory(0x80000000, 0x00010000, PPC_io_memory);
+
+ /* init basic PC hardware */
+ vga_initialize(pci_bus, ds, phys_ram_base + ram_size, ram_size,
+ vga_ram_size);
+ rtc_init(0x70, 8);
+ // openpic = openpic_init(0x00000000, 0xF0000000, 1);
+ // pic_init(openpic);
+ pic_init();
+ // pit = pit_init(0x40, 0);
+
+ serial_init(0x3f8, 4, serial_hds[0]);
+ nb_nics1 = nb_nics;
+ if (nb_nics1 > NE2000_NB_MAX)
+ nb_nics1 = NE2000_NB_MAX;
+ for(i = 0; i < nb_nics1; i++) {
+ isa_ne2000_init(ne2000_io[i], ne2000_irq[i], &nd_table[i]);
+ }
+
+ for(i = 0; i < 2; i++) {
+ isa_ide_init(ide_iobase[i], ide_iobase2[i], ide_irq[i],
+ bs_table[2 * i], bs_table[2 * i + 1]);
+ }
+ kbd_init();
+ DMA_init(1);
+ // AUD_init();
+ // SB16_init();
+
+ fdctrl_init(6, 2, 0, 0x3f0, fd_table);
+
+ /* Register speaker port */
+ register_ioport_read(0x61, 1, 1, speaker_ioport_read, NULL);
+ register_ioport_write(0x61, 1, 1, speaker_ioport_write, NULL);
+ /* Register fake IO ports for PREP */
+ register_ioport_read(0x398, 2, 1, &PREP_io_read, sysctrl);
+ register_ioport_write(0x398, 2, 1, &PREP_io_write, sysctrl);
+ /* System control ports */
+ register_ioport_read(0x0092, 0x01, 1, &PREP_io_800_readb, sysctrl);
+ register_ioport_write(0x0092, 0x01, 1, &PREP_io_800_writeb, sysctrl);
+ register_ioport_read(0x0800, 0x52, 1, &PREP_io_800_readb, sysctrl);
+ register_ioport_write(0x0800, 0x52, 1, &PREP_io_800_writeb, sysctrl);
+ /* PCI intack location */
+ PPC_io_memory = cpu_register_io_memory(0, PPC_intack_read,
+ PPC_intack_write, NULL);
+ cpu_register_physical_memory(0xBFFFFFF0, 0x4, PPC_io_memory);
+ /* PowerPC control and status register group */
+#if 0
+ PPC_io_memory = cpu_register_io_memory(0, PPC_XCSR_read, PPC_XCSR_write, NULL);
+ cpu_register_physical_memory(0xFEFF0000, 0x1000, PPC_io_memory);
+#endif
+
+ nvram = m48t59_init(8, 0, 0x0074, NVRAM_SIZE);
+ if (nvram == NULL)
+ return;
+ sysctrl->nvram = nvram;
+
+ /* Initialise NVRAM */
+ PPC_NVRAM_set_params(nvram, NVRAM_SIZE, "PREP", ram_size, boot_device,
+ kernel_base, kernel_size,
+ kernel_cmdline,
+ initrd_base, initrd_size,
+ /* XXX: need an option to load a NVRAM image */
+ 0,
+ graphic_width, graphic_height, graphic_depth);
+}
--- /dev/null
+/*
+ * QEMU Soundblaster 16 emulation
+ *
+ * Copyright (c) 2003-2004 Vassili Karpov (malc)
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+
+#define LENOFA(a) ((int) (sizeof(a)/sizeof(a[0])))
+
+#define dolog(...) AUD_log ("sb16", __VA_ARGS__)
+
+/* #define DEBUG */
+/* #define DEBUG_SB16_MOST */
+
+#ifdef DEBUG
+#define ldebug(...) dolog (__VA_ARGS__)
+#else
+#define ldebug(...)
+#endif
+
+#define IO_READ_PROTO(name) \
+ uint32_t name (void *opaque, uint32_t nport)
+#define IO_WRITE_PROTO(name) \
+ void name (void *opaque, uint32_t nport, uint32_t val)
+
+static const char e3[] = "COPYRIGHT (C) CREATIVE TECHNOLOGY LTD, 1992.";
+
+static struct {
+ int ver_lo;
+ int ver_hi;
+ int irq;
+ int dma;
+ int hdma;
+ int port;
+} conf = {5, 4, 5, 1, 5, 0x220};
+
+typedef struct SB16State {
+ int irq;
+ int dma;
+ int hdma;
+ int port;
+ int ver;
+
+ int in_index;
+ int out_data_len;
+ int fmt_stereo;
+ int fmt_signed;
+ int fmt_bits;
+ audfmt_e fmt;
+ int dma_auto;
+ int block_size;
+ int fifo;
+ int freq;
+ int time_const;
+ int speaker;
+ int needed_bytes;
+ int cmd;
+ int use_hdma;
+ int highspeed;
+ int can_write;
+
+ int v2x6;
+
+ uint8_t csp_param;
+ uint8_t csp_value;
+ uint8_t csp_mode;
+ uint8_t csp_regs[256];
+ uint8_t csp_index;
+ uint8_t csp_reg83[4];
+ int csp_reg83r;
+ int csp_reg83w;
+
+ uint8_t in2_data[10];
+ uint8_t out_data[50];
+ uint8_t test_reg;
+ uint8_t last_read_byte;
+ int nzero;
+
+ int left_till_irq;
+
+ int dma_running;
+ int bytes_per_second;
+ int align;
+ SWVoice *voice;
+
+ QEMUTimer *ts, *aux_ts;
+ /* mixer state */
+ int mixer_nreg;
+ uint8_t mixer_regs[256];
+} SB16State;
+
+/* XXX: suppress that and use a context */
+static struct SB16State dsp;
+
+static int magic_of_irq (int irq)
+{
+ switch (irq) {
+ case 5:
+ return 2;
+ case 7:
+ return 4;
+ case 9:
+ return 1;
+ case 10:
+ return 8;
+ default:
+ dolog ("bad irq %d\n", irq);
+ return 2;
+ }
+}
+
+static int irq_of_magic (int magic)
+{
+ switch (magic) {
+ case 1:
+ return 9;
+ case 2:
+ return 5;
+ case 4:
+ return 7;
+ case 8:
+ return 10;
+ default:
+ dolog ("bad irq magic %d\n", magic);
+ return -1;
+ }
+}
+
+#if 0
+static void log_dsp (SB16State *dsp)
+{
+ ldebug ("%s:%s:%d:%s:dmasize=%d:freq=%d:const=%d:speaker=%d\n",
+ dsp->fmt_stereo ? "Stereo" : "Mono",
+ dsp->fmt_signed ? "Signed" : "Unsigned",
+ dsp->fmt_bits,
+ dsp->dma_auto ? "Auto" : "Single",
+ dsp->block_size,
+ dsp->freq,
+ dsp->time_const,
+ dsp->speaker);
+}
+#endif
+
+static void speaker (SB16State *s, int on)
+{
+ s->speaker = on;
+ /* AUD_enable (s->voice, on); */
+}
+
+static void control (SB16State *s, int hold)
+{
+ int dma = s->use_hdma ? s->hdma : s->dma;
+ s->dma_running = hold;
+
+ ldebug ("hold %d high %d dma %d\n", hold, s->use_hdma, dma);
+
+ if (hold) {
+ DMA_hold_DREQ (dma);
+ AUD_enable (s->voice, 1);
+ }
+ else {
+ DMA_release_DREQ (dma);
+ AUD_enable (s->voice, 0);
+ }
+}
+
+static void aux_timer (void *opaque)
+{
+ SB16State *s = opaque;
+ s->can_write = 1;
+ pic_set_irq (s->irq, 1);
+}
+
+#define DMA8_AUTO 1
+#define DMA8_HIGH 2
+
+static void dma_cmd8 (SB16State *s, int mask, int dma_len)
+{
+ s->fmt = AUD_FMT_U8;
+ s->use_hdma = 0;
+ s->fmt_bits = 8;
+ s->fmt_signed = 0;
+ s->fmt_stereo = (s->mixer_regs[0x0e] & 2) != 0;
+ if (-1 == s->time_const) {
+ s->freq = 11025;
+ }
+ else {
+ int tmp = (256 - s->time_const);
+ s->freq = (1000000 + (tmp / 2)) / tmp;
+ }
+
+ if (dma_len != -1)
+ s->block_size = dma_len << s->fmt_stereo;
+ else {
+ /* This is apparently the only way to make both Act1/PL
+ and SecondReality/FC work
+
+ Act1 sets block size via command 0x48 and it's an odd number
+ SR does the same with even number
+ Both use stereo, and Creatives own documentation states that
+ 0x48 sets block size in bytes less one.. go figure */
+ s->block_size &= ~s->fmt_stereo;
+ }
+
+ s->freq >>= s->fmt_stereo;
+ s->left_till_irq = s->block_size;
+ s->bytes_per_second = (s->freq << s->fmt_stereo);
+ /* s->highspeed = (mask & DMA8_HIGH) != 0; */
+ s->dma_auto = (mask & DMA8_AUTO) != 0;
+ s->align = (1 << s->fmt_stereo) - 1;
+
+ if (s->block_size & s->align)
+ dolog ("warning: unaligned buffer\n");
+
+ ldebug ("freq %d, stereo %d, sign %d, bits %d, "
+ "dma %d, auto %d, fifo %d, high %d\n",
+ s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
+ s->block_size, s->dma_auto, s->fifo, s->highspeed);
+
+ if (s->freq)
+ s->voice = AUD_open (s->voice, "sb16", s->freq,
+ 1 << s->fmt_stereo, s->fmt);
+
+ control (s, 1);
+ speaker (s, 1);
+}
+
+static void dma_cmd (SB16State *s, uint8_t cmd, uint8_t d0, int dma_len)
+{
+ s->use_hdma = cmd < 0xc0;
+ s->fifo = (cmd >> 1) & 1;
+ s->dma_auto = (cmd >> 2) & 1;
+ s->fmt_signed = (d0 >> 4) & 1;
+ s->fmt_stereo = (d0 >> 5) & 1;
+
+ switch (cmd >> 4) {
+ case 11:
+ s->fmt_bits = 16;
+ break;
+
+ case 12:
+ s->fmt_bits = 8;
+ break;
+ }
+
+ if (-1 != s->time_const) {
+#if 1
+ int tmp = 256 - s->time_const;
+ s->freq = (1000000 + (tmp / 2)) / tmp;
+#else
+ /* s->freq = 1000000 / ((255 - s->time_const) << s->fmt_stereo); */
+ s->freq = 1000000 / ((255 - s->time_const));
+#endif
+ s->time_const = -1;
+ }
+
+ s->block_size = dma_len + 1;
+ s->block_size <<= (s->fmt_bits == 16);
+ if (!s->dma_auto) {
+ /* It is clear that for DOOM and auto-init this value
+ shouldn't take stereo into account, while Miles Sound Systems
+ setsound.exe with single transfer mode wouldn't work without it
+ wonders of SB16 yet again */
+ s->block_size <<= s->fmt_stereo;
+ }
+
+ ldebug ("freq %d, stereo %d, sign %d, bits %d, "
+ "dma %d, auto %d, fifo %d, high %d\n",
+ s->freq, s->fmt_stereo, s->fmt_signed, s->fmt_bits,
+ s->block_size, s->dma_auto, s->fifo, s->highspeed);
+
+ if (16 == s->fmt_bits) {
+ if (s->fmt_signed) {
+ s->fmt = AUD_FMT_S16;
+ }
+ else {
+ s->fmt = AUD_FMT_U16;
+ }
+ }
+ else {
+ if (s->fmt_signed) {
+ s->fmt = AUD_FMT_S8;
+ }
+ else {
+ s->fmt = AUD_FMT_U8;
+ }
+ }
+
+ s->left_till_irq = s->block_size;
+
+ s->bytes_per_second = (s->freq << s->fmt_stereo) << (s->fmt_bits == 16);
+ s->highspeed = 0;
+ s->align = (1 << (s->fmt_stereo + (s->fmt_bits == 16))) - 1;
+ if (s->block_size & s->align)
+ dolog ("warning: unaligned buffer\n");
+
+ if (s->freq)
+ s->voice = AUD_open (s->voice, "sb16", s->freq,
+ 1 << s->fmt_stereo, s->fmt);
+
+ control (s, 1);
+ speaker (s, 1);
+}
+
+static inline void dsp_out_data (SB16State *s, uint8_t val)
+{
+ ldebug ("outdata %#x\n", val);
+ if (s->out_data_len < sizeof (s->out_data))
+ s->out_data[s->out_data_len++] = val;
+}
+
+static inline uint8_t dsp_get_data (SB16State *s)
+{
+ if (s->in_index)
+ return s->in2_data[--s->in_index];
+ else {
+ dolog ("buffer underflow\n");
+ return 0;
+ }
+}
+
+static void command (SB16State *s, uint8_t cmd)
+{
+ ldebug ("command %#x\n", cmd);
+
+ if (cmd > 0xaf && cmd < 0xd0) {
+ if (cmd & 8) {
+ dolog ("ADC not yet supported (command %#x)\n", cmd);
+ }
+
+ switch (cmd >> 4) {
+ case 11:
+ case 12:
+ break;
+ default:
+ dolog ("%#x wrong bits\n", cmd);
+ }
+ s->needed_bytes = 3;
+ }
+ else {
+ switch (cmd) {
+ case 0x03:
+ dsp_out_data (s, 0x10); /* s->csp_param); */
+ goto warn;
+
+ case 0x04:
+ s->needed_bytes = 1;
+ goto warn;
+
+ case 0x05:
+ s->needed_bytes = 2;
+ goto warn;
+
+ case 0x08:
+ /* __asm__ ("int3"); */
+ goto warn;
+
+ case 0x0e:
+ s->needed_bytes = 2;
+ goto warn;
+
+ case 0x09:
+ dsp_out_data (s, 0xf8);
+ goto warn;
+
+ case 0x0f:
+ s->needed_bytes = 1;
+ goto warn;
+
+ case 0x10:
+ s->needed_bytes = 1;
+ goto warn;
+
+ case 0x14:
+ s->needed_bytes = 2;
+ s->block_size = 0;
+ break;
+
+ case 0x1c: /* Auto-Initialize DMA DAC, 8-bit */
+ control (s, 1);
+ break;
+
+ case 0x20: /* Direct ADC, Juice/PL */
+ dsp_out_data (s, 0xff);
+ goto warn;
+
+ case 0x35:
+ dolog ("MIDI command(0x35) not implemented\n");
+ break;
+
+ case 0x40:
+ s->freq = -1;
+ s->time_const = -1;
+ s->needed_bytes = 1;
+ break;
+
+ case 0x41:
+ s->freq = -1;
+ s->time_const = -1;
+ s->needed_bytes = 2;
+ break;
+
+ case 0x42:
+ s->freq = -1;
+ s->time_const = -1;
+ s->needed_bytes = 2;
+ goto warn;
+
+ case 0x45:
+ dsp_out_data (s, 0xaa);
+ goto warn;
+
+ case 0x47: /* Continue Auto-Initialize DMA 16bit */
+ break;
+
+ case 0x48:
+ s->needed_bytes = 2;
+ break;
+
+ case 0x80:
+ s->needed_bytes = 2;
+ break;
+
+ case 0x90:
+ case 0x91:
+ dma_cmd8 (s, ((cmd & 1) == 0) | DMA8_HIGH, -1);
+ break;
+
+ case 0xd0: /* halt DMA operation. 8bit */
+ control (s, 0);
+ break;
+
+ case 0xd1: /* speaker on */
+ speaker (s, 1);
+ break;
+
+ case 0xd3: /* speaker off */
+ speaker (s, 0);
+ break;
+
+ case 0xd4: /* continue DMA operation. 8bit */
+ control (s, 1);
+ break;
+
+ case 0xd5: /* halt DMA operation. 16bit */
+ control (s, 0);
+ break;
+
+ case 0xd6: /* continue DMA operation. 16bit */
+ control (s, 1);
+ break;
+
+ case 0xd9: /* exit auto-init DMA after this block. 16bit */
+ s->dma_auto = 0;
+ break;
+
+ case 0xda: /* exit auto-init DMA after this block. 8bit */
+ s->dma_auto = 0;
+ break;
+
+ case 0xe0:
+ s->needed_bytes = 1;
+ goto warn;
+
+ case 0xe1:
+ dsp_out_data (s, s->ver & 0xff);
+ dsp_out_data (s, s->ver >> 8);
+ break;
+
+ case 0xe2:
+ s->needed_bytes = 1;
+ goto warn;
+
+ case 0xe3:
+ {
+ int i;
+ for (i = sizeof (e3) - 1; i >= 0; --i)
+ dsp_out_data (s, e3[i]);
+ }
+ break;
+
+ case 0xe4: /* write test reg */
+ s->needed_bytes = 1;
+ break;
+
+ case 0xe7:
+ dolog ("Attempt to probe for ESS (0xe7)?\n");
+ return;
+
+ case 0xe8: /* read test reg */
+ dsp_out_data (s, s->test_reg);
+ break;
+
+ case 0xf2:
+ case 0xf3:
+ dsp_out_data (s, 0xaa);
+ s->mixer_regs[0x82] |= (cmd == 0xf2) ? 1 : 2;
+ pic_set_irq (s->irq, 1);
+ break;
+
+ case 0xf9:
+ s->needed_bytes = 1;
+ goto warn;
+
+ case 0xfa:
+ dsp_out_data (s, 0);
+ goto warn;
+
+ case 0xfc: /* FIXME */
+ dsp_out_data (s, 0);
+ goto warn;
+
+ default:
+ dolog ("unrecognized command %#x\n", cmd);
+ return;
+ }
+ }
+
+ s->cmd = cmd;
+ if (!s->needed_bytes)
+ ldebug ("\n");
+ return;
+
+ warn:
+ dolog ("warning: command %#x,%d is not trully understood yet\n",
+ cmd, s->needed_bytes);
+ s->cmd = cmd;
+ return;
+}
+
+static uint16_t dsp_get_lohi (SB16State *s)
+{
+ uint8_t hi = dsp_get_data (s);
+ uint8_t lo = dsp_get_data (s);
+ return (hi << 8) | lo;
+}
+
+static uint16_t dsp_get_hilo (SB16State *s)
+{
+ uint8_t lo = dsp_get_data (s);
+ uint8_t hi = dsp_get_data (s);
+ return (hi << 8) | lo;
+}
+
+static void complete (SB16State *s)
+{
+ int d0, d1, d2;
+ ldebug ("complete command %#x, in_index %d, needed_bytes %d\n",
+ s->cmd, s->in_index, s->needed_bytes);
+
+ if (s->cmd > 0xaf && s->cmd < 0xd0) {
+ d2 = dsp_get_data (s);
+ d1 = dsp_get_data (s);
+ d0 = dsp_get_data (s);
+
+ if (s->cmd & 8) {
+ dolog ("ADC params cmd = %#x d0 = %d, d1 = %d, d2 = %d\n",
+ s->cmd, d0, d1, d2);
+ }
+ else {
+ ldebug ("cmd = %#x d0 = %d, d1 = %d, d2 = %d\n",
+ s->cmd, d0, d1, d2);
+ dma_cmd (s, s->cmd, d0, d1 + (d2 << 8));
+ }
+ }
+ else {
+ switch (s->cmd) {
+ case 0x04:
+ s->csp_mode = dsp_get_data (s);
+ s->csp_reg83r = 0;
+ s->csp_reg83w = 0;
+ ldebug ("CSP command 0x04: mode=%#x\n", s->csp_mode);
+ break;
+
+ case 0x05:
+ s->csp_param = dsp_get_data (s);
+ s->csp_value = dsp_get_data (s);
+ ldebug ("CSP command 0x05: param=%#x value=%#x\n",
+ s->csp_param,
+ s->csp_value);
+ break;
+
+ case 0x0e:
+ d0 = dsp_get_data (s);
+ d1 = dsp_get_data (s);
+ ldebug ("write CSP register %d <- %#x\n", d1, d0);
+ if (d1 == 0x83) {
+ ldebug ("0x83[%d] <- %#x\n", s->csp_reg83r, d0);
+ s->csp_reg83[s->csp_reg83r % 4] = d0;
+ s->csp_reg83r += 1;
+ }
+ else
+ s->csp_regs[d1] = d0;
+ break;
+
+ case 0x0f:
+ d0 = dsp_get_data (s);
+ ldebug ("read CSP register %#x -> %#x, mode=%#x\n",
+ d0, s->csp_regs[d0], s->csp_mode);
+ if (d0 == 0x83) {
+ ldebug ("0x83[%d] -> %#x\n",
+ s->csp_reg83w,
+ s->csp_reg83[s->csp_reg83w % 4]);
+ dsp_out_data (s, s->csp_reg83[s->csp_reg83w % 4]);
+ s->csp_reg83w += 1;
+ }
+ else
+ dsp_out_data (s, s->csp_regs[d0]);
+ break;
+
+ case 0x10:
+ d0 = dsp_get_data (s);
+ dolog ("cmd 0x10 d0=%#x\n", d0);
+ break;
+
+ case 0x14:
+ dma_cmd8 (s, 0, dsp_get_lohi (s) + 1);
+ break;
+
+ case 0x40:
+ s->time_const = dsp_get_data (s);
+ ldebug ("set time const %d\n", s->time_const);
+ break;
+
+ case 0x42: /* FT2 sets output freq with this, go figure */
+ dolog ("cmd 0x42 might not do what it think it should\n");
+
+ case 0x41:
+ s->freq = dsp_get_hilo (s);
+ ldebug ("set freq %d\n", s->freq);
+ break;
+
+ case 0x48:
+ s->block_size = dsp_get_lohi (s) + 1;
+ ldebug ("set dma block len %d\n", s->block_size);
+ break;
+
+ case 0x80:
+ {
+ int freq, samples, bytes;
+ int64_t ticks;
+
+ freq = s->freq > 0 ? s->freq : 11025;
+ samples = dsp_get_lohi (s) + 1;
+ bytes = samples << s->fmt_stereo << (s->fmt_bits == 16);
+ ticks = (bytes * ticks_per_sec) / freq;
+ if (ticks < ticks_per_sec / 1024)
+ pic_set_irq (s->irq, 1);
+ else
+ qemu_mod_timer (s->aux_ts, qemu_get_clock (vm_clock) + ticks);
+ ldebug ("mix silence %d %d %lld\n", samples, bytes, ticks);
+ }
+ break;
+
+ case 0xe0:
+ d0 = dsp_get_data (s);
+ s->out_data_len = 0;
+ ldebug ("E0 data = %#x\n", d0);
+ dsp_out_data(s, ~d0);
+ break;
+
+ case 0xe2:
+ d0 = dsp_get_data (s);
+ ldebug ("E2 = %#x\n", d0);
+ break;
+
+ case 0xe4:
+ s->test_reg = dsp_get_data (s);
+ break;
+
+ case 0xf9:
+ d0 = dsp_get_data (s);
+ ldebug ("command 0xf9 with %#x\n", d0);
+ switch (d0) {
+ case 0x0e:
+ dsp_out_data (s, 0xff);
+ break;
+
+ case 0x0f:
+ dsp_out_data (s, 0x07);
+ break;
+
+ case 0x37:
+ dsp_out_data (s, 0x38);
+ break;
+
+ default:
+ dsp_out_data (s, 0x00);
+ break;
+ }
+ break;
+
+ default:
+ dolog ("complete: unrecognized command %#x\n", s->cmd);
+ return;
+ }
+ }
+
+ ldebug ("\n");
+ s->cmd = -1;
+ return;
+}
+
+static void reset (SB16State *s)
+{
+ pic_set_irq (s->irq, 0);
+ if (s->dma_auto) {
+ pic_set_irq (s->irq, 1);
+ pic_set_irq (s->irq, 0);
+ }
+
+ s->mixer_regs[0x82] = 0;
+ s->dma_auto = 0;
+ s->in_index = 0;
+ s->out_data_len = 0;
+ s->left_till_irq = 0;
+ s->needed_bytes = 0;
+ s->block_size = -1;
+ s->nzero = 0;
+ s->highspeed = 0;
+ s->v2x6 = 0;
+
+ dsp_out_data(s, 0xaa);
+ speaker (s, 0);
+ control (s, 0);
+}
+
+static IO_WRITE_PROTO (dsp_write)
+{
+ SB16State *s = opaque;
+ int iport;
+
+ iport = nport - s->port;
+
+ ldebug ("write %#x <- %#x\n", nport, val);
+ switch (iport) {
+ case 0x06:
+ switch (val) {
+ case 0x00:
+ if (s->v2x6 == 1) {
+ if (0 && s->highspeed) {
+ s->highspeed = 0;
+ pic_set_irq (s->irq, 0);
+ control (s, 0);
+ }
+ else
+ reset (s);
+ }
+ s->v2x6 = 0;
+ break;
+
+ case 0x01:
+ case 0x03: /* FreeBSD kludge */
+ s->v2x6 = 1;
+ break;
+
+ case 0xc6:
+ s->v2x6 = 0; /* Prince of Persia, csp.sys, diagnose.exe */
+ break;
+
+ case 0xb8: /* Panic */
+ reset (s);
+ break;
+
+ case 0x39:
+ dsp_out_data (s, 0x38);
+ reset (s);
+ s->v2x6 = 0x39;
+ break;
+
+ default:
+ s->v2x6 = val;
+ break;
+ }
+ break;
+
+ case 0x0c: /* write data or command | write status */
+/* if (s->highspeed) */
+/* break; */
+
+ if (0 == s->needed_bytes) {
+ command (s, val);
+#if 0
+ if (0 == s->needed_bytes) {
+ log_dsp (s);
+ }
+#endif
+ }
+ else {
+ if (s->in_index == sizeof (s->in2_data)) {
+ dolog ("in data overrun\n");
+ }
+ else {
+ s->in2_data[s->in_index++] = val;
+ if (s->in_index == s->needed_bytes) {
+ s->needed_bytes = 0;
+ complete (s);
+#if 0
+ log_dsp (s);
+#endif
+ }
+ }
+ }
+ break;
+
+ default:
+ ldebug ("(nport=%#x, val=%#x)\n", nport, val);
+ break;
+ }
+}
+
+static IO_READ_PROTO (dsp_read)
+{
+ SB16State *s = opaque;
+ int iport, retval, ack = 0;
+
+ iport = nport - s->port;
+
+ switch (iport) {
+ case 0x06: /* reset */
+ retval = 0xff;
+ break;
+
+ case 0x0a: /* read data */
+ if (s->out_data_len) {
+ retval = s->out_data[--s->out_data_len];
+ s->last_read_byte = retval;
+ }
+ else {
+ dolog ("empty output buffer\n");
+ retval = s->last_read_byte;
+ /* goto error; */
+ }
+ break;
+
+ case 0x0c: /* 0 can write */
+ retval = s->can_write ? 0 : 0x80;
+ break;
+
+ case 0x0d: /* timer interrupt clear */
+ /* dolog ("timer interrupt clear\n"); */
+ retval = 0;
+ break;
+
+ case 0x0e: /* data available status | irq 8 ack */
+ retval = (!s->out_data_len || s->highspeed) ? 0 : 0x80;
+ if (s->mixer_regs[0x82] & 1) {
+ ack = 1;
+ s->mixer_regs[0x82] &= 1;
+ pic_set_irq (s->irq, 0);
+ }
+ break;
+
+ case 0x0f: /* irq 16 ack */
+ retval = 0xff;
+ if (s->mixer_regs[0x82] & 2) {
+ ack = 1;
+ s->mixer_regs[0x82] &= 2;
+ pic_set_irq (s->irq, 0);
+ }
+ break;
+
+ default:
+ goto error;
+ }
+
+ if (!ack)
+ ldebug ("read %#x -> %#x\n", nport, retval);
+
+ return retval;
+
+ error:
+ dolog ("WARNING dsp_read %#x error\n", nport);
+ return 0xff;
+}
+
+static void reset_mixer (SB16State *s)
+{
+ int i;
+
+ memset (s->mixer_regs, 0xff, 0x7f);
+ memset (s->mixer_regs + 0x83, 0xff, sizeof (s->mixer_regs) - 0x83);
+
+ s->mixer_regs[0x02] = 4; /* master volume 3bits */
+ s->mixer_regs[0x06] = 4; /* MIDI volume 3bits */
+ s->mixer_regs[0x08] = 0; /* CD volume 3bits */
+ s->mixer_regs[0x0a] = 0; /* voice volume 2bits */
+
+ /* d5=input filt, d3=lowpass filt, d1,d2=input source */
+ s->mixer_regs[0x0c] = 0;
+
+ /* d5=output filt, d1=stereo switch */
+ s->mixer_regs[0x0e] = 0;
+
+ /* voice volume L d5,d7, R d1,d3 */
+ s->mixer_regs[0x04] = (4 << 5) | (4 << 1);
+ /* master ... */
+ s->mixer_regs[0x22] = (4 << 5) | (4 << 1);
+ /* MIDI ... */
+ s->mixer_regs[0x26] = (4 << 5) | (4 << 1);
+
+ for (i = 0x30; i < 0x48; i++) {
+ s->mixer_regs[i] = 0x20;
+ }
+}
+
+static IO_WRITE_PROTO(mixer_write_indexb)
+{
+ SB16State *s = opaque;
+ s->mixer_nreg = val;
+}
+
+static IO_WRITE_PROTO(mixer_write_datab)
+{
+ SB16State *s = opaque;
+
+ ldebug ("mixer_write [%#x] <- %#x\n", s->mixer_nreg, val);
+ if (s->mixer_nreg > sizeof (s->mixer_regs))
+ return;
+
+ switch (s->mixer_nreg) {
+ case 0x00:
+ reset_mixer (s);
+ break;
+
+ case 0x80:
+ {
+ int irq = irq_of_magic (val);
+ ldebug ("setting irq to %d (val=%#x)\n", irq, val);
+ if (irq > 0)
+ s->irq = irq;
+ }
+ break;
+
+ case 0x81:
+ {
+ int dma, hdma;
+
+ dma = lsbindex (val & 0xf);
+ hdma = lsbindex (val & 0xf0);
+ dolog ("attempt to set DMA register 8bit %d, 16bit %d (val=%#x)\n",
+ dma, hdma, val);
+#if 0
+ s->dma = dma;
+ s->hdma = hdma;
+#endif
+ }
+ break;
+
+ case 0x82:
+ dolog ("attempt to write into IRQ status register (val=%#x)\n",
+ val);
+ return;
+
+ default:
+ if (s->mixer_nreg >= 0x80)
+ dolog ("attempt to write mixer[%#x] <- %#x\n", s->mixer_nreg, val);
+ break;
+ }
+
+ s->mixer_regs[s->mixer_nreg] = val;
+}
+
+static IO_WRITE_PROTO(mixer_write_indexw)
+{
+ mixer_write_indexb (opaque, nport, val & 0xff);
+ mixer_write_datab (opaque, nport, (val >> 8) & 0xff);
+}
+
+static IO_READ_PROTO(mixer_read)
+{
+ SB16State *s = opaque;
+#ifndef DEBUG_SB16_MOST
+ if (s->mixer_nreg != 0x82)
+#endif
+ ldebug ("mixer_read[%#x] -> %#x\n",
+ s->mixer_nreg, s->mixer_regs[s->mixer_nreg]);
+ return s->mixer_regs[s->mixer_nreg];
+}
+
+static int write_audio (SB16State *s, int nchan, int dma_pos,
+ int dma_len, int len)
+{
+ int temp, net;
+ uint8_t tmpbuf[4096];
+
+ temp = len;
+ net = 0;
+
+ while (temp) {
+ int left = dma_len - dma_pos;
+ int to_copy, copied;
+
+ to_copy = audio_MIN (temp, left);
+ if (to_copy > sizeof(tmpbuf))
+ to_copy = sizeof(tmpbuf);
+
+ copied = DMA_read_memory (nchan, tmpbuf, dma_pos, to_copy);
+ copied = AUD_write (s->voice, tmpbuf, copied);
+
+ temp -= copied;
+ dma_pos = (dma_pos + copied) % dma_len;
+ net += copied;
+
+ if (!copied)
+ break;
+ }
+
+ return net;
+}
+
+static int SB_read_DMA (void *opaque, int nchan, int dma_pos, int dma_len)
+{
+ SB16State *s = opaque;
+ int free, rfree, till, copy, written, elapsed;
+
+ if (s->left_till_irq < 0) {
+ s->left_till_irq = s->block_size;
+ }
+
+ elapsed = AUD_calc_elapsed (s->voice);
+ free = elapsed;/* AUD_get_free (s->voice); */
+ rfree = free;
+ free = audio_MIN (free, elapsed) & ~s->align;
+
+ if ((free <= 0) || !dma_len) {
+ return dma_pos;
+ }
+
+ copy = free;
+ till = s->left_till_irq;
+
+#ifdef DEBUG_SB16_MOST
+ dolog ("pos:%06d free:%d,%d till:%d len:%d\n",
+ dma_pos, free, AUD_get_free (s->voice), till, dma_len);
+#endif
+
+ if (till <= copy) {
+ if (0 == s->dma_auto) {
+ copy = till;
+ }
+ }
+
+ written = write_audio (s, nchan, dma_pos, dma_len, copy);
+ dma_pos = (dma_pos + written) % dma_len;
+ s->left_till_irq -= written;
+
+ if (s->left_till_irq <= 0) {
+ s->mixer_regs[0x82] |= (nchan & 4) ? 2 : 1;
+ pic_set_irq (s->irq, 1);
+ if (0 == s->dma_auto) {
+ control (s, 0);
+ speaker (s, 0);
+ }
+ }
+
+#ifdef DEBUG_SB16_MOST
+ ldebug ("pos %5d free %5d size %5d till % 5d copy %5d written %5d size %5d\n",
+ dma_pos, free, dma_len, s->left_till_irq, copy, written,
+ s->block_size);
+#endif
+
+ while (s->left_till_irq <= 0) {
+ s->left_till_irq = s->block_size + s->left_till_irq;
+ }
+
+ AUD_adjust (s->voice, written);
+ return dma_pos;
+}
+
+void SB_timer (void *opaque)
+{
+ SB16State *s = opaque;
+ AUD_run ();
+ qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + 1);
+}
+
+static void SB_save (QEMUFile *f, void *opaque)
+{
+ SB16State *s = opaque;
+
+ qemu_put_be32s (f, &s->irq);
+ qemu_put_be32s (f, &s->dma);
+ qemu_put_be32s (f, &s->hdma);
+ qemu_put_be32s (f, &s->port);
+ qemu_put_be32s (f, &s->ver);
+ qemu_put_be32s (f, &s->in_index);
+ qemu_put_be32s (f, &s->out_data_len);
+ qemu_put_be32s (f, &s->fmt_stereo);
+ qemu_put_be32s (f, &s->fmt_signed);
+ qemu_put_be32s (f, &s->fmt_bits);
+ qemu_put_be32s (f, &s->fmt);
+ qemu_put_be32s (f, &s->dma_auto);
+ qemu_put_be32s (f, &s->block_size);
+ qemu_put_be32s (f, &s->fifo);
+ qemu_put_be32s (f, &s->freq);
+ qemu_put_be32s (f, &s->time_const);
+ qemu_put_be32s (f, &s->speaker);
+ qemu_put_be32s (f, &s->needed_bytes);
+ qemu_put_be32s (f, &s->cmd);
+ qemu_put_be32s (f, &s->use_hdma);
+ qemu_put_be32s (f, &s->highspeed);
+ qemu_put_be32s (f, &s->can_write);
+ qemu_put_be32s (f, &s->v2x6);
+
+ qemu_put_8s (f, &s->csp_param);
+ qemu_put_8s (f, &s->csp_value);
+ qemu_put_8s (f, &s->csp_mode);
+ qemu_put_8s (f, &s->csp_param);
+ qemu_put_buffer (f, s->csp_regs, 256);
+ qemu_put_8s (f, &s->csp_index);
+ qemu_put_buffer (f, s->csp_reg83, 4);
+ qemu_put_be32s (f, &s->csp_reg83r);
+ qemu_put_be32s (f, &s->csp_reg83w);
+
+ qemu_put_buffer (f, s->in2_data, sizeof (s->in2_data));
+ qemu_put_buffer (f, s->out_data, sizeof (s->out_data));
+ qemu_put_8s (f, &s->test_reg);
+ qemu_put_8s (f, &s->last_read_byte);
+
+ qemu_put_be32s (f, &s->nzero);
+ qemu_put_be32s (f, &s->left_till_irq);
+ qemu_put_be32s (f, &s->dma_running);
+ qemu_put_be32s (f, &s->bytes_per_second);
+ qemu_put_be32s (f, &s->align);
+
+ qemu_put_be32s (f, &s->mixer_nreg);
+ qemu_put_buffer (f, s->mixer_regs, 256);
+}
+
+static int SB_load (QEMUFile *f, void *opaque, int version_id)
+{
+ SB16State *s = opaque;
+
+ if (version_id != 1)
+ return -EINVAL;
+
+ qemu_get_be32s (f, &s->irq);
+ qemu_get_be32s (f, &s->dma);
+ qemu_get_be32s (f, &s->hdma);
+ qemu_get_be32s (f, &s->port);
+ qemu_get_be32s (f, &s->ver);
+ qemu_get_be32s (f, &s->in_index);
+ qemu_get_be32s (f, &s->out_data_len);
+ qemu_get_be32s (f, &s->fmt_stereo);
+ qemu_get_be32s (f, &s->fmt_signed);
+ qemu_get_be32s (f, &s->fmt_bits);
+ qemu_get_be32s (f, &s->fmt);
+ qemu_get_be32s (f, &s->dma_auto);
+ qemu_get_be32s (f, &s->block_size);
+ qemu_get_be32s (f, &s->fifo);
+ qemu_get_be32s (f, &s->freq);
+ qemu_get_be32s (f, &s->time_const);
+ qemu_get_be32s (f, &s->speaker);
+ qemu_get_be32s (f, &s->needed_bytes);
+ qemu_get_be32s (f, &s->cmd);
+ qemu_get_be32s (f, &s->use_hdma);
+ qemu_get_be32s (f, &s->highspeed);
+ qemu_get_be32s (f, &s->can_write);
+ qemu_get_be32s (f, &s->v2x6);
+
+ qemu_get_8s (f, &s->csp_param);
+ qemu_get_8s (f, &s->csp_value);
+ qemu_get_8s (f, &s->csp_mode);
+ qemu_get_8s (f, &s->csp_param);
+ qemu_get_buffer (f, s->csp_regs, 256);
+ qemu_get_8s (f, &s->csp_index);
+ qemu_get_buffer (f, s->csp_reg83, 4);
+ qemu_get_be32s (f, &s->csp_reg83r);
+ qemu_get_be32s (f, &s->csp_reg83w);
+
+ qemu_get_buffer (f, s->in2_data, sizeof (s->in2_data));
+ qemu_get_buffer (f, s->out_data, sizeof (s->out_data));
+ qemu_get_8s (f, &s->test_reg);
+ qemu_get_8s (f, &s->last_read_byte);
+
+ qemu_get_be32s (f, &s->nzero);
+ qemu_get_be32s (f, &s->left_till_irq);
+ qemu_get_be32s (f, &s->dma_running);
+ qemu_get_be32s (f, &s->bytes_per_second);
+ qemu_get_be32s (f, &s->align);
+
+ qemu_get_be32s (f, &s->mixer_nreg);
+ qemu_get_buffer (f, s->mixer_regs, 256);
+
+ if (s->voice) {
+ AUD_close (s->voice);
+ s->voice = NULL;
+ }
+
+ if (s->dma_running) {
+ if (s->freq)
+ s->voice = AUD_open (s->voice, "sb16", s->freq,
+ 1 << s->fmt_stereo, s->fmt);
+
+ control (s, 1);
+ speaker (s, s->speaker);
+ }
+ return 0;
+}
+
+void SB16_init (void)
+{
+ SB16State *s = &dsp;
+ int i;
+ static const uint8_t dsp_write_ports[] = {0x6, 0xc};
+ static const uint8_t dsp_read_ports[] = {0x6, 0xa, 0xc, 0xd, 0xe, 0xf};
+
+ s->ts = qemu_new_timer (vm_clock, SB_timer, s);
+ if (!s->ts)
+ return;
+
+ s->irq = conf.irq;
+ s->dma = conf.dma;
+ s->hdma = conf.hdma;
+ s->port = conf.port;
+ s->ver = conf.ver_lo | (conf.ver_hi << 8);
+
+ s->mixer_regs[0x80] = magic_of_irq (s->irq);
+ s->mixer_regs[0x81] = (1 << s->dma) | (1 << s->hdma);
+ s->mixer_regs[0x82] = 2 << 5;
+
+ s->csp_regs[5] = 1;
+ s->csp_regs[9] = 0xf8;
+
+ reset_mixer (s);
+ s->aux_ts = qemu_new_timer (vm_clock, aux_timer, s);
+ if (!s->aux_ts)
+ return;
+
+ for (i = 0; i < LENOFA (dsp_write_ports); i++) {
+ register_ioport_write (s->port + dsp_write_ports[i], 1, 1, dsp_write, s);
+ }
+
+ for (i = 0; i < LENOFA (dsp_read_ports); i++) {
+ register_ioport_read (s->port + dsp_read_ports[i], 1, 1, dsp_read, s);
+ }
+
+ register_ioport_write (s->port + 0x4, 1, 1, mixer_write_indexb, s);
+ register_ioport_write (s->port + 0x4, 1, 2, mixer_write_indexw, s);
+ register_ioport_read (s->port + 0x5, 1, 1, mixer_read, s);
+ register_ioport_write (s->port + 0x5, 1, 1, mixer_write_datab, s);
+
+ DMA_register_channel (s->hdma, SB_read_DMA, s);
+ DMA_register_channel (s->dma, SB_read_DMA, s);
+ s->can_write = 1;
+
+ qemu_mod_timer (s->ts, qemu_get_clock (vm_clock) + 1);
+ register_savevm ("sb16", 0, 1, SB_save, SB_load, s);
+}
--- /dev/null
+/*
+ * QEMU interrupt controller emulation
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+//#define DEBUG_IRQ_COUNT
+
+/* These registers are used for sending/receiving irqs from/to
+ * different cpu's.
+ */
+struct sun4m_intreg_percpu {
+ unsigned int tbt; /* Intrs pending for this cpu, by PIL. */
+ /* These next two registers are WRITE-ONLY and are only
+ * "on bit" sensitive, "off bits" written have NO affect.
+ */
+ unsigned int clear; /* Clear this cpus irqs here. */
+ unsigned int set; /* Set this cpus irqs here. */
+};
+/*
+ * djhr
+ * Actually the clear and set fields in this struct are misleading..
+ * according to the SLAVIO manual (and the same applies for the SEC)
+ * the clear field clears bits in the mask which will ENABLE that IRQ
+ * the set field sets bits in the mask to DISABLE the IRQ.
+ *
+ * Also the undirected_xx address in the SLAVIO is defined as
+ * RESERVED and write only..
+ *
+ * DAVEM_NOTE: The SLAVIO only specifies behavior on uniprocessor
+ * sun4m machines, for MP the layout makes more sense.
+ */
+struct sun4m_intreg_master {
+ unsigned int tbt; /* IRQ's that are pending, see sun4m masks. */
+ unsigned int irqs; /* Master IRQ bits. */
+
+ /* Again, like the above, two these registers are WRITE-ONLY. */
+ unsigned int clear; /* Clear master IRQ's by setting bits here. */
+ unsigned int set; /* Set master IRQ's by setting bits here. */
+
+ /* This register is both READ and WRITE. */
+ unsigned int undirected_target; /* Which cpu gets undirected irqs. */
+};
+
+#define SUN4M_INT_ENABLE 0x80000000
+#define SUN4M_INT_E14 0x00000080
+#define SUN4M_INT_E10 0x00080000
+
+#define SUN4M_HARD_INT(x) (0x000000001 << (x))
+#define SUN4M_SOFT_INT(x) (0x000010000 << (x))
+
+#define SUN4M_INT_MASKALL 0x80000000 /* mask all interrupts */
+#define SUN4M_INT_MODULE_ERR 0x40000000 /* module error */
+#define SUN4M_INT_M2S_WRITE 0x20000000 /* write buffer error */
+#define SUN4M_INT_ECC 0x10000000 /* ecc memory error */
+#define SUN4M_INT_FLOPPY 0x00400000 /* floppy disk */
+#define SUN4M_INT_MODULE 0x00200000 /* module interrupt */
+#define SUN4M_INT_VIDEO 0x00100000 /* onboard video */
+#define SUN4M_INT_REALTIME 0x00080000 /* system timer */
+#define SUN4M_INT_SCSI 0x00040000 /* onboard scsi */
+#define SUN4M_INT_AUDIO 0x00020000 /* audio/isdn */
+#define SUN4M_INT_ETHERNET 0x00010000 /* onboard ethernet */
+#define SUN4M_INT_SERIAL 0x00008000 /* serial ports */
+#define SUN4M_INT_SBUSBITS 0x00003F80 /* sbus int bits */
+
+#define SUN4M_INT_SBUS(x) (1 << (x+7))
+#define SUN4M_INT_VME(x) (1 << (x))
+
+typedef struct SCHEDState {
+ uint32_t addr, addrg;
+ uint32_t intreg_pending;
+ uint32_t intreg_enabled;
+ uint32_t intregm_pending;
+ uint32_t intregm_enabled;
+} SCHEDState;
+
+static SCHEDState *ps;
+
+#ifdef DEBUG_IRQ_COUNT
+static uint64_t irq_count[32];
+#endif
+
+static uint32_t intreg_mem_readl(void *opaque, target_phys_addr_t addr)
+{
+ SCHEDState *s = opaque;
+ uint32_t saddr;
+
+ saddr = (addr - s->addr) >> 2;
+ switch (saddr) {
+ case 0:
+ return s->intreg_pending;
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static void intreg_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ SCHEDState *s = opaque;
+ uint32_t saddr;
+
+ saddr = (addr - s->addr) >> 2;
+ switch (saddr) {
+ case 0:
+ s->intreg_pending = val;
+ break;
+ case 1: // clear
+ s->intreg_enabled &= ~val;
+ break;
+ case 2: // set
+ s->intreg_enabled |= val;
+ break;
+ default:
+ break;
+ }
+}
+
+static CPUReadMemoryFunc *intreg_mem_read[3] = {
+ intreg_mem_readl,
+ intreg_mem_readl,
+ intreg_mem_readl,
+};
+
+static CPUWriteMemoryFunc *intreg_mem_write[3] = {
+ intreg_mem_writel,
+ intreg_mem_writel,
+ intreg_mem_writel,
+};
+
+static uint32_t intregm_mem_readl(void *opaque, target_phys_addr_t addr)
+{
+ SCHEDState *s = opaque;
+ uint32_t saddr;
+
+ saddr = (addr - s->addrg) >> 2;
+ switch (saddr) {
+ case 0:
+ return s->intregm_pending;
+ break;
+ case 1:
+ return s->intregm_enabled;
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+static void intregm_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ SCHEDState *s = opaque;
+ uint32_t saddr;
+
+ saddr = (addr - s->addrg) >> 2;
+ switch (saddr) {
+ case 0:
+ s->intregm_pending = val;
+ break;
+ case 1:
+ s->intregm_enabled = val;
+ break;
+ case 2: // clear
+ s->intregm_enabled &= ~val;
+ break;
+ case 3: // set
+ s->intregm_enabled |= val;
+ break;
+ default:
+ break;
+ }
+}
+
+static CPUReadMemoryFunc *intregm_mem_read[3] = {
+ intregm_mem_readl,
+ intregm_mem_readl,
+ intregm_mem_readl,
+};
+
+static CPUWriteMemoryFunc *intregm_mem_write[3] = {
+ intregm_mem_writel,
+ intregm_mem_writel,
+ intregm_mem_writel,
+};
+
+void pic_info(void)
+{
+ term_printf("per-cpu: pending 0x%08x, enabled 0x%08x\n", ps->intreg_pending, ps->intreg_enabled);
+ term_printf("master: pending 0x%08x, enabled 0x%08x\n", ps->intregm_pending, ps->intregm_enabled);
+}
+
+void irq_info(void)
+{
+#ifndef DEBUG_IRQ_COUNT
+ term_printf("irq statistic code not compiled.\n");
+#else
+ int i;
+ int64_t count;
+
+ term_printf("IRQ statistics:\n");
+ for (i = 0; i < 32; i++) {
+ count = irq_count[i];
+ if (count > 0)
+ term_printf("%2d: %lld\n", i, count);
+ }
+#endif
+}
+
+static const unsigned int intr_to_mask[16] = {
+ 0, 0, 0, 0, 0, 0, SUN4M_INT_ETHERNET, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+void pic_set_irq(int irq, int level)
+{
+ if (irq < 16) {
+ unsigned int mask = intr_to_mask[irq];
+ ps->intreg_pending |= 1 << irq;
+ if (ps->intregm_enabled & mask) {
+ cpu_single_env->interrupt_index = irq;
+ cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HARD);
+ }
+ }
+#ifdef DEBUG_IRQ_COUNT
+ if (level == 1)
+ irq_count[irq]++;
+#endif
+}
+
+void sched_init(uint32_t addr, uint32_t addrg)
+{
+ int intreg_io_memory, intregm_io_memory;
+ SCHEDState *s;
+
+ s = qemu_mallocz(sizeof(SCHEDState));
+ if (!s)
+ return;
+ s->addr = addr;
+ s->addrg = addrg;
+
+ intreg_io_memory = cpu_register_io_memory(0, intreg_mem_read, intreg_mem_write, s);
+ cpu_register_physical_memory(addr, 3, intreg_io_memory);
+
+ intregm_io_memory = cpu_register_io_memory(0, intregm_mem_read, intregm_mem_write, s);
+ cpu_register_physical_memory(addrg, 5, intregm_io_memory);
+
+ ps = s;
+}
+
--- /dev/null
+/*
+ * QEMU 16450 UART emulation
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+
+//#define DEBUG_SERIAL
+
+#define UART_LCR_DLAB 0x80 /* Divisor latch access bit */
+
+#define UART_IER_MSI 0x08 /* Enable Modem status interrupt */
+#define UART_IER_RLSI 0x04 /* Enable receiver line status interrupt */
+#define UART_IER_THRI 0x02 /* Enable Transmitter holding register int. */
+#define UART_IER_RDI 0x01 /* Enable receiver data interrupt */
+
+#define UART_IIR_NO_INT 0x01 /* No interrupts pending */
+#define UART_IIR_ID 0x06 /* Mask for the interrupt ID */
+
+#define UART_IIR_MSI 0x00 /* Modem status interrupt */
+#define UART_IIR_THRI 0x02 /* Transmitter holding register empty */
+#define UART_IIR_RDI 0x04 /* Receiver data interrupt */
+#define UART_IIR_RLSI 0x06 /* Receiver line status interrupt */
+
+/*
+ * These are the definitions for the Modem Control Register
+ */
+#define UART_MCR_LOOP 0x10 /* Enable loopback test mode */
+#define UART_MCR_OUT2 0x08 /* Out2 complement */
+#define UART_MCR_OUT1 0x04 /* Out1 complement */
+#define UART_MCR_RTS 0x02 /* RTS complement */
+#define UART_MCR_DTR 0x01 /* DTR complement */
+
+/*
+ * These are the definitions for the Modem Status Register
+ */
+#define UART_MSR_DCD 0x80 /* Data Carrier Detect */
+#define UART_MSR_RI 0x40 /* Ring Indicator */
+#define UART_MSR_DSR 0x20 /* Data Set Ready */
+#define UART_MSR_CTS 0x10 /* Clear to Send */
+#define UART_MSR_DDCD 0x08 /* Delta DCD */
+#define UART_MSR_TERI 0x04 /* Trailing edge ring indicator */
+#define UART_MSR_DDSR 0x02 /* Delta DSR */
+#define UART_MSR_DCTS 0x01 /* Delta CTS */
+#define UART_MSR_ANY_DELTA 0x0F /* Any of the delta bits! */
+
+#define UART_LSR_TEMT 0x40 /* Transmitter empty */
+#define UART_LSR_THRE 0x20 /* Transmit-hold-register empty */
+#define UART_LSR_BI 0x10 /* Break interrupt indicator */
+#define UART_LSR_FE 0x08 /* Frame error indicator */
+#define UART_LSR_PE 0x04 /* Parity error indicator */
+#define UART_LSR_OE 0x02 /* Overrun error indicator */
+#define UART_LSR_DR 0x01 /* Receiver data ready */
+
+struct SerialState {
+ uint8_t divider;
+ uint8_t rbr; /* receive register */
+ uint8_t ier;
+ uint8_t iir; /* read only */
+ uint8_t lcr;
+ uint8_t mcr;
+ uint8_t lsr; /* read only */
+ uint8_t msr;
+ uint8_t scr;
+ /* NOTE: this hidden state is necessary for tx irq generation as
+ it can be reset while reading iir */
+ int thr_ipending;
+ int irq;
+ CharDriverState *chr;
+};
+
+static void serial_update_irq(SerialState *s)
+{
+ if ((s->lsr & UART_LSR_DR) && (s->ier & UART_IER_RDI)) {
+ s->iir = UART_IIR_RDI;
+ } else if (s->thr_ipending && (s->ier & UART_IER_THRI)) {
+ s->iir = UART_IIR_THRI;
+ } else {
+ s->iir = UART_IIR_NO_INT;
+ }
+ if (s->iir != UART_IIR_NO_INT) {
+ pic_set_irq(s->irq, 1);
+ } else {
+ pic_set_irq(s->irq, 0);
+ }
+}
+
+static void serial_ioport_write(void *opaque, uint32_t addr, uint32_t val)
+{
+ SerialState *s = opaque;
+ unsigned char ch;
+
+ addr &= 7;
+#ifdef DEBUG_SERIAL
+ printf("serial: write addr=0x%02x val=0x%02x\n", addr, val);
+#endif
+ switch(addr) {
+ default:
+ case 0:
+ if (s->lcr & UART_LCR_DLAB) {
+ s->divider = (s->divider & 0xff00) | val;
+ } else {
+ s->thr_ipending = 0;
+ s->lsr &= ~UART_LSR_THRE;
+ serial_update_irq(s);
+ ch = val;
+ qemu_chr_write(s->chr, &ch, 1);
+ s->thr_ipending = 1;
+ s->lsr |= UART_LSR_THRE;
+ s->lsr |= UART_LSR_TEMT;
+ serial_update_irq(s);
+ }
+ break;
+ case 1:
+ if (s->lcr & UART_LCR_DLAB) {
+ s->divider = (s->divider & 0x00ff) | (val << 8);
+ } else {
+ s->ier = val & 0x0f;
+ if (s->lsr & UART_LSR_THRE) {
+ s->thr_ipending = 1;
+ }
+ serial_update_irq(s);
+ }
+ break;
+ case 2:
+ break;
+ case 3:
+ s->lcr = val;
+ break;
+ case 4:
+ s->mcr = val & 0x1f;
+ break;
+ case 5:
+ break;
+ case 6:
+ s->msr = val;
+ break;
+ case 7:
+ s->scr = val;
+ break;
+ }
+}
+
+static uint32_t serial_ioport_read(void *opaque, uint32_t addr)
+{
+ SerialState *s = opaque;
+ uint32_t ret;
+
+ addr &= 7;
+ switch(addr) {
+ default:
+ case 0:
+ if (s->lcr & UART_LCR_DLAB) {
+ ret = s->divider & 0xff;
+ } else {
+ ret = s->rbr;
+ s->lsr &= ~(UART_LSR_DR | UART_LSR_BI);
+ serial_update_irq(s);
+ }
+ break;
+ case 1:
+ if (s->lcr & UART_LCR_DLAB) {
+ ret = (s->divider >> 8) & 0xff;
+ } else {
+ ret = s->ier;
+ }
+ break;
+ case 2:
+ ret = s->iir;
+ /* reset THR pending bit */
+ if ((ret & 0x7) == UART_IIR_THRI)
+ s->thr_ipending = 0;
+ serial_update_irq(s);
+ break;
+ case 3:
+ ret = s->lcr;
+ break;
+ case 4:
+ ret = s->mcr;
+ break;
+ case 5:
+ ret = s->lsr;
+ break;
+ case 6:
+ if (s->mcr & UART_MCR_LOOP) {
+ /* in loopback, the modem output pins are connected to the
+ inputs */
+ ret = (s->mcr & 0x0c) << 4;
+ ret |= (s->mcr & 0x02) << 3;
+ ret |= (s->mcr & 0x01) << 5;
+ } else {
+ ret = s->msr;
+ }
+ break;
+ case 7:
+ ret = s->scr;
+ break;
+ }
+#ifdef DEBUG_SERIAL
+ printf("serial: read addr=0x%02x val=0x%02x\n", addr, ret);
+#endif
+ return ret;
+}
+
+static int serial_can_receive(SerialState *s)
+{
+ return !(s->lsr & UART_LSR_DR);
+}
+
+static void serial_receive_byte(SerialState *s, int ch)
+{
+ s->rbr = ch;
+ s->lsr |= UART_LSR_DR;
+ serial_update_irq(s);
+}
+
+static void serial_receive_break(SerialState *s)
+{
+ s->rbr = 0;
+ s->lsr |= UART_LSR_BI | UART_LSR_DR;
+ serial_update_irq(s);
+}
+
+static int serial_can_receive1(void *opaque)
+{
+ SerialState *s = opaque;
+ return serial_can_receive(s);
+}
+
+static void serial_receive1(void *opaque, const uint8_t *buf, int size)
+{
+ SerialState *s = opaque;
+ serial_receive_byte(s, buf[0]);
+}
+
+static void serial_event(void *opaque, int event)
+{
+ SerialState *s = opaque;
+ if (event == CHR_EVENT_BREAK)
+ serial_receive_break(s);
+}
+
+/* If fd is zero, it means that the serial device uses the console */
+SerialState *serial_init(int base, int irq, CharDriverState *chr)
+{
+ SerialState *s;
+
+ s = qemu_mallocz(sizeof(SerialState));
+ if (!s)
+ return NULL;
+ s->irq = irq;
+ s->lsr = UART_LSR_TEMT | UART_LSR_THRE;
+ s->iir = UART_IIR_NO_INT;
+
+ register_ioport_write(base, 8, 1, serial_ioport_write, s);
+ register_ioport_read(base, 8, 1, serial_ioport_read, s);
+ s->chr = chr;
+ qemu_chr_add_read_handler(chr, serial_can_receive1, serial_receive1, s);
+ qemu_chr_add_event_handler(chr, serial_event);
+ return s;
+}
--- /dev/null
+/*
+ * QEMU Sun4m System Emulator
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+#include "m48t08.h"
+
+#define KERNEL_LOAD_ADDR 0x00004000
+#define MMU_CONTEXT_TBL 0x00003000
+#define MMU_L1PTP (MMU_CONTEXT_TBL + 0x0400)
+#define MMU_L2PTP (MMU_CONTEXT_TBL + 0x0800)
+#define PROM_ADDR 0xffd04000
+#define PROM_FILENAMEB "proll.bin"
+#define PROM_FILENAMEE "proll.elf"
+#define PROLL_MAGIC_ADDR 0x20000000
+#define PHYS_JJ_EEPROM 0x71200000 /* [2000] MK48T08 */
+#define PHYS_JJ_IDPROM_OFF 0x1FD8
+#define PHYS_JJ_EEPROM_SIZE 0x2000
+#define PHYS_JJ_IOMMU 0x10000000 /* First page of sun4m IOMMU */
+#define PHYS_JJ_TCX_FB 0x50800000 /* Start address, frame buffer body */
+#define PHYS_JJ_TCX_0E 0x5E000000 /* Top address, one byte used. */
+#define PHYS_JJ_IOMMU 0x10000000 /* First page of sun4m IOMMU */
+#define PHYS_JJ_LEDMA 0x78400010 /* ledma, off by 10 from unused SCSI */
+#define PHYS_JJ_LE 0x78C00000 /* LANCE, typical sun4m */
+#define PHYS_JJ_LE_IRQ 6
+#define PHYS_JJ_CLOCK 0x71D00000
+#define PHYS_JJ_CLOCK_IRQ 10
+#define PHYS_JJ_CLOCK1 0x71D10000
+#define PHYS_JJ_CLOCK1_IRQ 14
+#define PHYS_JJ_INTR0 0x71E00000 /* CPU0 interrupt control registers */
+#define PHYS_JJ_INTR_G 0x71E10000 /* Master interrupt control registers */
+
+/* TSC handling */
+
+uint64_t cpu_get_tsc()
+{
+ return qemu_get_clock(vm_clock);
+}
+
+void DMA_run() {}
+void SB16_run() {}
+int serial_can_receive(SerialState *s) { return 0; }
+void serial_receive_byte(SerialState *s, int ch) {}
+void serial_receive_break(SerialState *s) {}
+
+static m48t08_t *nvram;
+
+/* Sun4m hardware initialisation */
+void sun4m_init(int ram_size, int vga_ram_size, int boot_device,
+ DisplayState *ds, const char **fd_filename, int snapshot,
+ const char *kernel_filename, const char *kernel_cmdline,
+ const char *initrd_filename)
+{
+ char buf[1024];
+ int ret, linux_boot;
+ unsigned long bios_offset;
+
+ linux_boot = (kernel_filename != NULL);
+
+ /* allocate RAM */
+ cpu_register_physical_memory(0, ram_size, 0);
+ bios_offset = ram_size;
+
+ iommu_init(PHYS_JJ_IOMMU);
+ sched_init(PHYS_JJ_INTR0, PHYS_JJ_INTR_G);
+ tcx_init(ds, PHYS_JJ_TCX_FB);
+ lance_init(&nd_table[0], PHYS_JJ_LE_IRQ, PHYS_JJ_LE, PHYS_JJ_LEDMA);
+ nvram = m48t08_init(PHYS_JJ_EEPROM, PHYS_JJ_EEPROM_SIZE, &nd_table[0].macaddr);
+ timer_init(PHYS_JJ_CLOCK, PHYS_JJ_CLOCK_IRQ);
+ timer_init(PHYS_JJ_CLOCK1, PHYS_JJ_CLOCK1_IRQ);
+ magic_init(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR, PROLL_MAGIC_ADDR);
+
+ /* We load Proll as the kernel and start it. It will issue a magic
+ IO to load the real kernel */
+ if (linux_boot) {
+ snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAMEB);
+ ret = load_kernel(buf,
+ phys_ram_base + KERNEL_LOAD_ADDR);
+ if (ret < 0) {
+ fprintf(stderr, "qemu: could not load kernel '%s'\n",
+ buf);
+ exit(1);
+ }
+ }
+ /* Setup a MMU entry for entire address space */
+ stl_raw(phys_ram_base + MMU_CONTEXT_TBL, (MMU_L1PTP >> 4) | 1);
+ stl_raw(phys_ram_base + MMU_L1PTP, (MMU_L2PTP >> 4) | 1);
+ stl_raw(phys_ram_base + MMU_L1PTP + (0x01 << 2), (MMU_L2PTP >> 4) | 1); // 01.. == 00..
+ stl_raw(phys_ram_base + MMU_L1PTP + (0xff << 2), (MMU_L2PTP >> 4) | 1); // ff.. == 00..
+ stl_raw(phys_ram_base + MMU_L1PTP + (0xf0 << 2), (MMU_L2PTP >> 4) | 1); // f0.. == 00..
+ /* 3 = U:RWX S:RWX */
+ stl_raw(phys_ram_base + MMU_L2PTP, (3 << PTE_ACCESS_SHIFT) | 2);
+ stl_raw(phys_ram_base + MMU_L2PTP, ((0x01 << PTE_PPN_SHIFT) >> 4 ) | (3 << PTE_ACCESS_SHIFT) | 2);
+}
--- /dev/null
+/*
+ * QEMU Sun4m System Emulator
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+
+#define MAXX 1024
+#define MAXY 768
+#define XSZ (8*80)
+#define YSZ (24*11)
+#define XOFF (MAXX-XSZ)
+#define YOFF (MAXY-YSZ)
+
+typedef struct TCXState {
+ uint32_t addr;
+ DisplayState *ds;
+ uint8_t *vram;
+} TCXState;
+
+static TCXState *ts;
+
+void vga_update_display()
+{
+ dpy_update(ts->ds, 0, 0, XSZ, YSZ);
+}
+
+void vga_invalidate_display() {}
+
+static uint32_t tcx_mem_readb(void *opaque, target_phys_addr_t addr)
+{
+ TCXState *s = opaque;
+ uint32_t saddr;
+ unsigned int x, y;
+
+ saddr = addr - s->addr - YOFF*MAXX - XOFF;
+ y = saddr / MAXX;
+ x = saddr - y * MAXX;
+ if (x < XSZ && y < YSZ) {
+ return s->vram[y * XSZ + x];
+ }
+ return 0;
+}
+
+static uint32_t tcx_mem_readw(void *opaque, target_phys_addr_t addr)
+{
+ uint32_t v;
+#ifdef TARGET_WORDS_BIGENDIAN
+ v = tcx_mem_readb(opaque, addr) << 8;
+ v |= tcx_mem_readb(opaque, addr + 1);
+#else
+ v = tcx_mem_readb(opaque, addr);
+ v |= tcx_mem_readb(opaque, addr + 1) << 8;
+#endif
+ return v;
+}
+
+static uint32_t tcx_mem_readl(void *opaque, target_phys_addr_t addr)
+{
+ uint32_t v;
+#ifdef TARGET_WORDS_BIGENDIAN
+ v = tcx_mem_readb(opaque, addr) << 24;
+ v |= tcx_mem_readb(opaque, addr + 1) << 16;
+ v |= tcx_mem_readb(opaque, addr + 2) << 8;
+ v |= tcx_mem_readb(opaque, addr + 3);
+#else
+ v = tcx_mem_readb(opaque, addr);
+ v |= tcx_mem_readb(opaque, addr + 1) << 8;
+ v |= tcx_mem_readb(opaque, addr + 2) << 16;
+ v |= tcx_mem_readb(opaque, addr + 3) << 24;
+#endif
+ return v;
+}
+
+static void tcx_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ TCXState *s = opaque;
+ uint32_t saddr;
+ unsigned int x, y;
+ char *sptr;
+
+ saddr = addr - s->addr - YOFF*MAXX - XOFF;
+ y = saddr / MAXX;
+ x = saddr - y * MAXX;
+ if (x < XSZ && y < YSZ) {
+ sptr = s->ds->data;
+ if (sptr) {
+ if (s->ds->depth == 24 || s->ds->depth == 32) {
+ /* XXX need to do CLUT translation */
+ sptr[y * s->ds->linesize + x*4] = val & 0xff;
+ sptr[y * s->ds->linesize + x*4+1] = val & 0xff;
+ sptr[y * s->ds->linesize + x*4+2] = val & 0xff;
+ }
+ else if (s->ds->depth == 8) {
+ sptr[y * s->ds->linesize + x] = val & 0xff;
+ }
+ }
+ cpu_physical_memory_set_dirty(addr);
+ s->vram[y * XSZ + x] = val & 0xff;
+ }
+}
+
+static void tcx_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+#ifdef TARGET_WORDS_BIGENDIAN
+ tcx_mem_writeb(opaque, addr, (val >> 8) & 0xff);
+ tcx_mem_writeb(opaque, addr + 1, val & 0xff);
+#else
+ tcx_mem_writeb(opaque, addr, val & 0xff);
+ tcx_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
+#endif
+}
+
+static void tcx_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+#ifdef TARGET_WORDS_BIGENDIAN
+ tcx_mem_writeb(opaque, addr, (val >> 24) & 0xff);
+ tcx_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff);
+ tcx_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff);
+ tcx_mem_writeb(opaque, addr + 3, val & 0xff);
+#else
+ tcx_mem_writeb(opaque, addr, val & 0xff);
+ tcx_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
+ tcx_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
+ tcx_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
+#endif
+}
+
+static CPUReadMemoryFunc *tcx_mem_read[3] = {
+ tcx_mem_readb,
+ tcx_mem_readw,
+ tcx_mem_readl,
+};
+
+static CPUWriteMemoryFunc *tcx_mem_write[3] = {
+ tcx_mem_writeb,
+ tcx_mem_writew,
+ tcx_mem_writel,
+};
+
+void tcx_init(DisplayState *ds, uint32_t addr)
+{
+ TCXState *s;
+ int tcx_io_memory;
+
+ s = qemu_mallocz(sizeof(TCXState));
+ if (!s)
+ return;
+ s->ds = ds;
+ s->addr = addr;
+ ts = s;
+ tcx_io_memory = cpu_register_io_memory(0, tcx_mem_read, tcx_mem_write, s);
+ cpu_register_physical_memory(addr, 0x100000,
+ tcx_io_memory);
+ s->vram = qemu_mallocz(XSZ*YSZ);
+ dpy_resize(s->ds, XSZ, YSZ);
+}
+
+void vga_screen_dump(const char *filename)
+{
+ TCXState *s = ts;
+ FILE *f;
+ uint8_t *d, *d1;
+ unsigned int v;
+ int y, x;
+
+ f = fopen(filename, "wb");
+ if (!f)
+ return -1;
+ fprintf(f, "P6\n%d %d\n%d\n",
+ XSZ, YSZ, 255);
+ d1 = s->vram;
+ for(y = 0; y < YSZ; y++) {
+ d = d1;
+ for(x = 0; x < XSZ; x++) {
+ v = *d;
+ fputc((v) & 0xff, f);
+ fputc((v) & 0xff, f);
+ fputc((v) & 0xff, f);
+ d++;
+ }
+ d1 += XSZ;
+ }
+ fclose(f);
+ return;
+}
+
+
+
--- /dev/null
+/*
+ * QEMU Sparc timer controller emulation
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+
+/*
+ * Registers of hardware timer in sun4m.
+ */
+struct sun4m_timer_percpu {
+ volatile unsigned int l14_timer_limit; /* Initial value is 0x009c4000 */
+ volatile unsigned int l14_cur_count;
+};
+
+struct sun4m_timer_global {
+ volatile unsigned int l10_timer_limit;
+ volatile unsigned int l10_cur_count;
+};
+
+typedef struct TIMERState {
+ uint32_t addr;
+ uint32_t timer_regs[2];
+ int irq;
+} TIMERState;
+
+static uint32_t timer_mem_readl(void *opaque, target_phys_addr_t addr)
+{
+ TIMERState *s = opaque;
+ uint32_t saddr;
+
+ saddr = (addr - s->addr) >> 2;
+ switch (saddr) {
+ default:
+ return s->timer_regs[saddr];
+ break;
+ }
+ return 0;
+}
+
+static void timer_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ TIMERState *s = opaque;
+ uint32_t saddr;
+
+ saddr = (addr - s->addr) >> 2;
+ switch (saddr) {
+ default:
+ s->timer_regs[saddr] = val;
+ break;
+ }
+}
+
+static CPUReadMemoryFunc *timer_mem_read[3] = {
+ timer_mem_readl,
+ timer_mem_readl,
+ timer_mem_readl,
+};
+
+static CPUWriteMemoryFunc *timer_mem_write[3] = {
+ timer_mem_writel,
+ timer_mem_writel,
+ timer_mem_writel,
+};
+
+void timer_init(uint32_t addr, int irq)
+{
+ int timer_io_memory;
+ TIMERState *s;
+
+ s = qemu_mallocz(sizeof(TIMERState));
+ if (!s)
+ return;
+ s->addr = addr;
+ s->irq = irq;
+
+ timer_io_memory = cpu_register_io_memory(0, timer_mem_read, timer_mem_write, s);
+ cpu_register_physical_memory(addr, 2, timer_io_memory);
+}
--- /dev/null
+/*
+ * QEMU VGA Emulator.
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+#include "vga_int.h"
+
+//#define DEBUG_VGA
+//#define DEBUG_VGA_MEM
+//#define DEBUG_VGA_REG
+
+//#define DEBUG_S3
+//#define DEBUG_BOCHS_VBE
+
+/* S3 VGA is deprecated - another graphic card will be emulated */
+//#define CONFIG_S3VGA
+
+/* force some bits to zero */
+const uint8_t sr_mask[8] = {
+ (uint8_t)~0xfc,
+ (uint8_t)~0xc2,
+ (uint8_t)~0xf0,
+ (uint8_t)~0xc0,
+ (uint8_t)~0xf1,
+ (uint8_t)~0xff,
+ (uint8_t)~0xff,
+ (uint8_t)~0x00,
+};
+
+const uint8_t gr_mask[16] = {
+ (uint8_t)~0xf0, /* 0x00 */
+ (uint8_t)~0xf0, /* 0x01 */
+ (uint8_t)~0xf0, /* 0x02 */
+ (uint8_t)~0xe0, /* 0x03 */
+ (uint8_t)~0xfc, /* 0x04 */
+ (uint8_t)~0x84, /* 0x05 */
+ (uint8_t)~0xf0, /* 0x06 */
+ (uint8_t)~0xf0, /* 0x07 */
+ (uint8_t)~0x00, /* 0x08 */
+ (uint8_t)~0xff, /* 0x09 */
+ (uint8_t)~0xff, /* 0x0a */
+ (uint8_t)~0xff, /* 0x0b */
+ (uint8_t)~0xff, /* 0x0c */
+ (uint8_t)~0xff, /* 0x0d */
+ (uint8_t)~0xff, /* 0x0e */
+ (uint8_t)~0xff, /* 0x0f */
+};
+
+#define cbswap_32(__x) \
+((uint32_t)( \
+ (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
+ (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \
+ (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \
+ (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) ))
+
+#ifdef WORDS_BIGENDIAN
+#define PAT(x) cbswap_32(x)
+#else
+#define PAT(x) (x)
+#endif
+
+#ifdef WORDS_BIGENDIAN
+#define BIG 1
+#else
+#define BIG 0
+#endif
+
+#ifdef WORDS_BIGENDIAN
+#define GET_PLANE(data, p) (((data) >> (24 - (p) * 8)) & 0xff)
+#else
+#define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff)
+#endif
+
+static const uint32_t mask16[16] = {
+ PAT(0x00000000),
+ PAT(0x000000ff),
+ PAT(0x0000ff00),
+ PAT(0x0000ffff),
+ PAT(0x00ff0000),
+ PAT(0x00ff00ff),
+ PAT(0x00ffff00),
+ PAT(0x00ffffff),
+ PAT(0xff000000),
+ PAT(0xff0000ff),
+ PAT(0xff00ff00),
+ PAT(0xff00ffff),
+ PAT(0xffff0000),
+ PAT(0xffff00ff),
+ PAT(0xffffff00),
+ PAT(0xffffffff),
+};
+
+#undef PAT
+
+#ifdef WORDS_BIGENDIAN
+#define PAT(x) (x)
+#else
+#define PAT(x) cbswap_32(x)
+#endif
+
+static const uint32_t dmask16[16] = {
+ PAT(0x00000000),
+ PAT(0x000000ff),
+ PAT(0x0000ff00),
+ PAT(0x0000ffff),
+ PAT(0x00ff0000),
+ PAT(0x00ff00ff),
+ PAT(0x00ffff00),
+ PAT(0x00ffffff),
+ PAT(0xff000000),
+ PAT(0xff0000ff),
+ PAT(0xff00ff00),
+ PAT(0xff00ffff),
+ PAT(0xffff0000),
+ PAT(0xffff00ff),
+ PAT(0xffffff00),
+ PAT(0xffffffff),
+};
+
+static const uint32_t dmask4[4] = {
+ PAT(0x00000000),
+ PAT(0x0000ffff),
+ PAT(0xffff0000),
+ PAT(0xffffffff),
+};
+
+static uint32_t expand4[256];
+static uint16_t expand2[256];
+static uint8_t expand4to8[16];
+
+VGAState *vga_state;
+int vga_io_memory;
+
+static uint32_t vga_ioport_read(void *opaque, uint32_t addr)
+{
+ VGAState *s = opaque;
+ int val, index;
+
+ /* check port range access depending on color/monochrome mode */
+ if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||
+ (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION))) {
+ val = 0xff;
+ } else {
+ switch(addr) {
+ case 0x3c0:
+ if (s->ar_flip_flop == 0) {
+ val = s->ar_index;
+ } else {
+ val = 0;
+ }
+ break;
+ case 0x3c1:
+ index = s->ar_index & 0x1f;
+ if (index < 21)
+ val = s->ar[index];
+ else
+ val = 0;
+ break;
+ case 0x3c2:
+ val = s->st00;
+ break;
+ case 0x3c4:
+ val = s->sr_index;
+ break;
+ case 0x3c5:
+ val = s->sr[s->sr_index];
+#ifdef DEBUG_VGA_REG
+ printf("vga: read SR%x = 0x%02x\n", s->sr_index, val);
+#endif
+ break;
+ case 0x3c7:
+ val = s->dac_state;
+ break;
+ case 0x3c8:
+ val = s->dac_write_index;
+ break;
+ case 0x3c9:
+ val = s->palette[s->dac_read_index * 3 + s->dac_sub_index];
+ if (++s->dac_sub_index == 3) {
+ s->dac_sub_index = 0;
+ s->dac_read_index++;
+ }
+ break;
+ case 0x3ca:
+ val = s->fcr;
+ break;
+ case 0x3cc:
+ val = s->msr;
+ break;
+ case 0x3ce:
+ val = s->gr_index;
+ break;
+ case 0x3cf:
+ val = s->gr[s->gr_index];
+#ifdef DEBUG_VGA_REG
+ printf("vga: read GR%x = 0x%02x\n", s->gr_index, val);
+#endif
+ break;
+ case 0x3b4:
+ case 0x3d4:
+ val = s->cr_index;
+ break;
+ case 0x3b5:
+ case 0x3d5:
+ val = s->cr[s->cr_index];
+#ifdef DEBUG_VGA_REG
+ printf("vga: read CR%x = 0x%02x\n", s->cr_index, val);
+#endif
+#ifdef DEBUG_S3
+ if (s->cr_index >= 0x20)
+ printf("S3: CR read index=0x%x val=0x%x\n",
+ s->cr_index, val);
+#endif
+ break;
+ case 0x3ba:
+ case 0x3da:
+ /* just toggle to fool polling */
+ s->st01 ^= ST01_V_RETRACE | ST01_DISP_ENABLE;
+ val = s->st01;
+ s->ar_flip_flop = 0;
+ break;
+ default:
+ val = 0x00;
+ break;
+ }
+ }
+#if defined(DEBUG_VGA)
+ printf("VGA: read addr=0x%04x data=0x%02x\n", addr, val);
+#endif
+ return val;
+}
+
+static void vga_ioport_write(void *opaque, uint32_t addr, uint32_t val)
+{
+ VGAState *s = opaque;
+ int index;
+
+ /* check port range access depending on color/monochrome mode */
+ if ((addr >= 0x3b0 && addr <= 0x3bf && (s->msr & MSR_COLOR_EMULATION)) ||
+ (addr >= 0x3d0 && addr <= 0x3df && !(s->msr & MSR_COLOR_EMULATION)))
+ return;
+
+#ifdef DEBUG_VGA
+ printf("VGA: write addr=0x%04x data=0x%02x\n", addr, val);
+#endif
+
+ switch(addr) {
+ case 0x3c0:
+ if (s->ar_flip_flop == 0) {
+ val &= 0x3f;
+ s->ar_index = val;
+ } else {
+ index = s->ar_index & 0x1f;
+ switch(index) {
+ case 0x00 ... 0x0f:
+ s->ar[index] = val & 0x3f;
+ break;
+ case 0x10:
+ s->ar[index] = val & ~0x10;
+ break;
+ case 0x11:
+ s->ar[index] = val;
+ break;
+ case 0x12:
+ s->ar[index] = val & ~0xc0;
+ break;
+ case 0x13:
+ s->ar[index] = val & ~0xf0;
+ break;
+ case 0x14:
+ s->ar[index] = val & ~0xf0;
+ break;
+ default:
+ break;
+ }
+ }
+ s->ar_flip_flop ^= 1;
+ break;
+ case 0x3c2:
+ s->msr = val & ~0x10;
+ break;
+ case 0x3c4:
+ s->sr_index = val & 7;
+ break;
+ case 0x3c5:
+#ifdef DEBUG_VGA_REG
+ printf("vga: write SR%x = 0x%02x\n", s->sr_index, val);
+#endif
+ s->sr[s->sr_index] = val & sr_mask[s->sr_index];
+ break;
+ case 0x3c7:
+ s->dac_read_index = val;
+ s->dac_sub_index = 0;
+ s->dac_state = 3;
+ break;
+ case 0x3c8:
+ s->dac_write_index = val;
+ s->dac_sub_index = 0;
+ s->dac_state = 0;
+ break;
+ case 0x3c9:
+ s->dac_cache[s->dac_sub_index] = val;
+ if (++s->dac_sub_index == 3) {
+ memcpy(&s->palette[s->dac_write_index * 3], s->dac_cache, 3);
+ s->dac_sub_index = 0;
+ s->dac_write_index++;
+ }
+ break;
+ case 0x3ce:
+ s->gr_index = val & 0x0f;
+ break;
+ case 0x3cf:
+#ifdef DEBUG_VGA_REG
+ printf("vga: write GR%x = 0x%02x\n", s->gr_index, val);
+#endif
+ s->gr[s->gr_index] = val & gr_mask[s->gr_index];
+ break;
+ case 0x3b4:
+ case 0x3d4:
+ s->cr_index = val;
+ break;
+ case 0x3b5:
+ case 0x3d5:
+#ifdef DEBUG_VGA_REG
+ printf("vga: write CR%x = 0x%02x\n", s->cr_index, val);
+#endif
+ /* handle CR0-7 protection */
+ if ((s->cr[0x11] & 0x80) && s->cr_index <= 7) {
+ /* can always write bit 4 of CR7 */
+ if (s->cr_index == 7)
+ s->cr[7] = (s->cr[7] & ~0x10) | (val & 0x10);
+ return;
+ }
+ switch(s->cr_index) {
+ case 0x01: /* horizontal display end */
+ case 0x07:
+ case 0x09:
+ case 0x0c:
+ case 0x0d:
+ case 0x12: /* veritcal display end */
+ s->cr[s->cr_index] = val;
+ break;
+
+#ifdef CONFIG_S3VGA
+ /* S3 registers */
+ case 0x2d:
+ case 0x2e:
+ case 0x2f:
+ case 0x30:
+ /* chip ID, cannot write */
+ break;
+ case 0x31:
+ /* update start address */
+ {
+ int v;
+ s->cr[s->cr_index] = val;
+ v = (val >> 4) & 3;
+ s->cr[0x69] = (s->cr[69] & ~0x03) | v;
+ }
+ break;
+ case 0x51:
+ /* update start address */
+ {
+ int v;
+ s->cr[s->cr_index] = val;
+ v = val & 3;
+ s->cr[0x69] = (s->cr[69] & ~0x0c) | (v << 2);
+ }
+ break;
+#endif
+ default:
+ s->cr[s->cr_index] = val;
+ break;
+ }
+#ifdef DEBUG_S3
+ if (s->cr_index >= 0x20)
+ printf("S3: CR write index=0x%x val=0x%x\n",
+ s->cr_index, val);
+#endif
+ break;
+ case 0x3ba:
+ case 0x3da:
+ s->fcr = val & 0x10;
+ break;
+ }
+}
+
+#ifdef CONFIG_BOCHS_VBE
+static uint32_t vbe_ioport_read_index(void *opaque, uint32_t addr)
+{
+ VGAState *s = opaque;
+ uint32_t val;
+ val = s->vbe_index;
+ return val;
+}
+
+static uint32_t vbe_ioport_read_data(void *opaque, uint32_t addr)
+{
+ VGAState *s = opaque;
+ uint32_t val;
+
+ if (s->vbe_index <= VBE_DISPI_INDEX_NB)
+ val = s->vbe_regs[s->vbe_index];
+ else
+ val = 0;
+#ifdef DEBUG_BOCHS_VBE
+ printf("VBE: read index=0x%x val=0x%x\n", s->vbe_index, val);
+#endif
+ return val;
+}
+
+static void vbe_ioport_write_index(void *opaque, uint32_t addr, uint32_t val)
+{
+ VGAState *s = opaque;
+ s->vbe_index = val;
+}
+
+static void vbe_ioport_write_data(void *opaque, uint32_t addr, uint32_t val)
+{
+ VGAState *s = opaque;
+
+ if (s->vbe_index <= VBE_DISPI_INDEX_NB) {
+#ifdef DEBUG_BOCHS_VBE
+ printf("VBE: write index=0x%x val=0x%x\n", s->vbe_index, val);
+#endif
+ switch(s->vbe_index) {
+ case VBE_DISPI_INDEX_ID:
+ if (val == VBE_DISPI_ID0 ||
+ val == VBE_DISPI_ID1 ||
+ val == VBE_DISPI_ID2) {
+ s->vbe_regs[s->vbe_index] = val;
+ }
+ break;
+ case VBE_DISPI_INDEX_XRES:
+ if ((val <= VBE_DISPI_MAX_XRES) && ((val & 7) == 0)) {
+ s->vbe_regs[s->vbe_index] = val;
+ }
+ break;
+ case VBE_DISPI_INDEX_YRES:
+ if (val <= VBE_DISPI_MAX_YRES) {
+ s->vbe_regs[s->vbe_index] = val;
+ }
+ break;
+ case VBE_DISPI_INDEX_BPP:
+ if (val == 0)
+ val = 8;
+ if (val == 4 || val == 8 || val == 15 ||
+ val == 16 || val == 24 || val == 32) {
+ s->vbe_regs[s->vbe_index] = val;
+ }
+ break;
+ case VBE_DISPI_INDEX_BANK:
+ val &= s->vbe_bank_mask;
+ s->vbe_regs[s->vbe_index] = val;
+ s->bank_offset = (val << 16);
+ break;
+ case VBE_DISPI_INDEX_ENABLE:
+ if (val & VBE_DISPI_ENABLED) {
+ int h, shift_control;
+
+ s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] =
+ s->vbe_regs[VBE_DISPI_INDEX_XRES];
+ s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] =
+ s->vbe_regs[VBE_DISPI_INDEX_YRES];
+ s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET] = 0;
+ s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET] = 0;
+
+ if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
+ s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 1;
+ else
+ s->vbe_line_offset = s->vbe_regs[VBE_DISPI_INDEX_XRES] *
+ ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
+ s->vbe_start_addr = 0;
+
+ /* clear the screen (should be done in BIOS) */
+ if (!(val & VBE_DISPI_NOCLEARMEM)) {
+ memset(s->vram_ptr, 0,
+ s->vbe_regs[VBE_DISPI_INDEX_YRES] * s->vbe_line_offset);
+ }
+
+ /* we initialize the VGA graphic mode (should be done
+ in BIOS) */
+ s->gr[0x06] = (s->gr[0x06] & ~0x0c) | 0x05; /* graphic mode + memory map 1 */
+ s->cr[0x17] |= 3; /* no CGA modes */
+ s->cr[0x13] = s->vbe_line_offset >> 3;
+ /* width */
+ s->cr[0x01] = (s->vbe_regs[VBE_DISPI_INDEX_XRES] >> 3) - 1;
+ /* height */
+ h = s->vbe_regs[VBE_DISPI_INDEX_YRES] - 1;
+ s->cr[0x12] = h;
+ s->cr[0x07] = (s->cr[0x07] & ~0x42) |
+ ((h >> 7) & 0x02) | ((h >> 3) & 0x40);
+ /* line compare to 1023 */
+ s->cr[0x18] = 0xff;
+ s->cr[0x07] |= 0x10;
+ s->cr[0x09] |= 0x40;
+
+ if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4) {
+ shift_control = 0;
+ s->sr[0x01] &= ~8; /* no double line */
+ } else {
+ shift_control = 2;
+ s->sr[4] |= 0x08; /* set chain 4 mode */
+ s->sr[2] |= 0x0f; /* activate all planes */
+ }
+ s->gr[0x05] = (s->gr[0x05] & ~0x60) | (shift_control << 5);
+ s->cr[0x09] &= ~0x9f; /* no double scan */
+ } else {
+ /* XXX: the bios should do that */
+ s->bank_offset = 0;
+ }
+ s->vbe_regs[s->vbe_index] = val;
+ break;
+ case VBE_DISPI_INDEX_VIRT_WIDTH:
+ {
+ int w, h, line_offset;
+
+ if (val < s->vbe_regs[VBE_DISPI_INDEX_XRES])
+ return;
+ w = val;
+ if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
+ line_offset = w >> 1;
+ else
+ line_offset = w * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
+ h = s->vram_size / line_offset;
+ /* XXX: support weird bochs semantics ? */
+ if (h < s->vbe_regs[VBE_DISPI_INDEX_YRES])
+ return;
+ s->vbe_regs[VBE_DISPI_INDEX_VIRT_WIDTH] = w;
+ s->vbe_regs[VBE_DISPI_INDEX_VIRT_HEIGHT] = h;
+ s->vbe_line_offset = line_offset;
+ }
+ break;
+ case VBE_DISPI_INDEX_X_OFFSET:
+ case VBE_DISPI_INDEX_Y_OFFSET:
+ {
+ int x;
+ s->vbe_regs[s->vbe_index] = val;
+ s->vbe_start_addr = s->vbe_line_offset * s->vbe_regs[VBE_DISPI_INDEX_Y_OFFSET];
+ x = s->vbe_regs[VBE_DISPI_INDEX_X_OFFSET];
+ if (s->vbe_regs[VBE_DISPI_INDEX_BPP] == 4)
+ s->vbe_start_addr += x >> 1;
+ else
+ s->vbe_start_addr += x * ((s->vbe_regs[VBE_DISPI_INDEX_BPP] + 7) >> 3);
+ s->vbe_start_addr >>= 2;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+}
+#endif
+
+extern FILE *logfile;
+/* called for accesses between 0xa0000 and 0xc0000 */
+uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr)
+{
+ VGAState *s = opaque;
+ int memory_map_mode, plane;
+ uint32_t ret;
+
+ /* convert to VGA memory offset */
+ memory_map_mode = (s->gr[6] >> 2) & 3;
+ addr &= 0x1ffff;
+ switch(memory_map_mode) {
+ case 0:
+ break;
+ case 1:
+ if (addr >= 0x10000)
+ return 0xff;
+ addr += s->bank_offset;
+ break;
+ case 2:
+ addr -= 0x10000;
+ if (addr >= 0x8000)
+ return 0xff;
+ break;
+ default:
+ case 3:
+ addr -= 0x18000;
+ if (addr >= 0x8000)
+ return 0xff;
+ break;
+ }
+
+ if (s->sr[4] & 0x08) {
+ /* chain 4 mode : simplest access */
+ ret = s->vram_ptr[addr];
+ } else if (s->gr[5] & 0x10) {
+ /* odd/even mode (aka text mode mapping) */
+ plane = (s->gr[4] & 2) | (addr & 1);
+ ret = s->vram_ptr[((addr & ~1) << 1) | plane];
+ } else {
+ /* standard VGA latched access */
+ s->latch = ((uint32_t *)s->vram_ptr)[addr];
+
+ if (!(s->gr[5] & 0x08)) {
+ /* read mode 0 */
+ plane = s->gr[4];
+ ret = GET_PLANE(s->latch, plane);
+ } else {
+ /* read mode 1 */
+ ret = (s->latch ^ mask16[s->gr[2]]) & mask16[s->gr[7]];
+ ret |= ret >> 16;
+ ret |= ret >> 8;
+ ret = (~ret) & 0xff;
+ }
+ }
+ return ret;
+}
+
+static uint32_t vga_mem_readw(void *opaque, target_phys_addr_t addr)
+{
+ uint32_t v;
+#ifdef TARGET_WORDS_BIGENDIAN
+ v = vga_mem_readb(opaque, addr) << 8;
+ v |= vga_mem_readb(opaque, addr + 1);
+#else
+ v = vga_mem_readb(opaque, addr);
+ v |= vga_mem_readb(opaque, addr + 1) << 8;
+#endif
+ return v;
+}
+
+static uint32_t vga_mem_readl(void *opaque, target_phys_addr_t addr)
+{
+ uint32_t v;
+#ifdef TARGET_WORDS_BIGENDIAN
+ v = vga_mem_readb(opaque, addr) << 24;
+ v |= vga_mem_readb(opaque, addr + 1) << 16;
+ v |= vga_mem_readb(opaque, addr + 2) << 8;
+ v |= vga_mem_readb(opaque, addr + 3);
+#else
+ v = vga_mem_readb(opaque, addr);
+ v |= vga_mem_readb(opaque, addr + 1) << 8;
+ v |= vga_mem_readb(opaque, addr + 2) << 16;
+ v |= vga_mem_readb(opaque, addr + 3) << 24;
+#endif
+ return v;
+}
+
+/* called for accesses between 0xa0000 and 0xc0000 */
+void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+ VGAState *s = opaque;
+ int memory_map_mode, plane, write_mode, b, func_select, mask;
+ uint32_t write_mask, bit_mask, set_mask;
+
+#ifdef DEBUG_VGA_MEM
+ printf("vga: [0x%x] = 0x%02x\n", addr, val);
+#endif
+ /* convert to VGA memory offset */
+ memory_map_mode = (s->gr[6] >> 2) & 3;
+ addr &= 0x1ffff;
+ switch(memory_map_mode) {
+ case 0:
+ break;
+ case 1:
+ if (addr >= 0x10000)
+ return;
+ addr += s->bank_offset;
+ break;
+ case 2:
+ addr -= 0x10000;
+ if (addr >= 0x8000)
+ return;
+ break;
+ default:
+ case 3:
+ addr -= 0x18000;
+ if (addr >= 0x8000)
+ return;
+ break;
+ }
+
+ if (s->sr[4] & 0x08) {
+ /* chain 4 mode : simplest access */
+ plane = addr & 3;
+ mask = (1 << plane);
+ if (s->sr[2] & mask) {
+ s->vram_ptr[addr] = val;
+#ifdef DEBUG_VGA_MEM
+ printf("vga: chain4: [0x%x]\n", addr);
+#endif
+ s->plane_updated |= mask; /* only used to detect font change */
+ cpu_physical_memory_set_dirty(s->vram_offset + addr);
+ }
+ } else if (s->gr[5] & 0x10) {
+ /* odd/even mode (aka text mode mapping) */
+ plane = (s->gr[4] & 2) | (addr & 1);
+ mask = (1 << plane);
+ if (s->sr[2] & mask) {
+ addr = ((addr & ~1) << 1) | plane;
+ s->vram_ptr[addr] = val;
+#ifdef DEBUG_VGA_MEM
+ printf("vga: odd/even: [0x%x]\n", addr);
+#endif
+ s->plane_updated |= mask; /* only used to detect font change */
+ cpu_physical_memory_set_dirty(s->vram_offset + addr);
+ }
+ } else {
+ /* standard VGA latched access */
+ write_mode = s->gr[5] & 3;
+ switch(write_mode) {
+ default:
+ case 0:
+ /* rotate */
+ b = s->gr[3] & 7;
+ val = ((val >> b) | (val << (8 - b))) & 0xff;
+ val |= val << 8;
+ val |= val << 16;
+
+ /* apply set/reset mask */
+ set_mask = mask16[s->gr[1]];
+ val = (val & ~set_mask) | (mask16[s->gr[0]] & set_mask);
+ bit_mask = s->gr[8];
+ break;
+ case 1:
+ val = s->latch;
+ goto do_write;
+ case 2:
+ val = mask16[val & 0x0f];
+ bit_mask = s->gr[8];
+ break;
+ case 3:
+ /* rotate */
+ b = s->gr[3] & 7;
+ val = (val >> b) | (val << (8 - b));
+
+ bit_mask = s->gr[8] & val;
+ val = mask16[s->gr[0]];
+ break;
+ }
+
+ /* apply logical operation */
+ func_select = s->gr[3] >> 3;
+ switch(func_select) {
+ case 0:
+ default:
+ /* nothing to do */
+ break;
+ case 1:
+ /* and */
+ val &= s->latch;
+ break;
+ case 2:
+ /* or */
+ val |= s->latch;
+ break;
+ case 3:
+ /* xor */
+ val ^= s->latch;
+ break;
+ }
+
+ /* apply bit mask */
+ bit_mask |= bit_mask << 8;
+ bit_mask |= bit_mask << 16;
+ val = (val & bit_mask) | (s->latch & ~bit_mask);
+
+ do_write:
+ /* mask data according to sr[2] */
+ mask = s->sr[2];
+ s->plane_updated |= mask; /* only used to detect font change */
+ write_mask = mask16[mask];
+ ((uint32_t *)s->vram_ptr)[addr] =
+ (((uint32_t *)s->vram_ptr)[addr] & ~write_mask) |
+ (val & write_mask);
+#ifdef DEBUG_VGA_MEM
+ printf("vga: latch: [0x%x] mask=0x%08x val=0x%08x\n",
+ addr * 4, write_mask, val);
+#endif
+ cpu_physical_memory_set_dirty(s->vram_offset + (addr << 2));
+ }
+}
+
+static void vga_mem_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+#ifdef TARGET_WORDS_BIGENDIAN
+ vga_mem_writeb(opaque, addr, (val >> 8) & 0xff);
+ vga_mem_writeb(opaque, addr + 1, val & 0xff);
+#else
+ vga_mem_writeb(opaque, addr, val & 0xff);
+ vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
+#endif
+}
+
+static void vga_mem_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
+{
+#ifdef TARGET_WORDS_BIGENDIAN
+ vga_mem_writeb(opaque, addr, (val >> 24) & 0xff);
+ vga_mem_writeb(opaque, addr + 1, (val >> 16) & 0xff);
+ vga_mem_writeb(opaque, addr + 2, (val >> 8) & 0xff);
+ vga_mem_writeb(opaque, addr + 3, val & 0xff);
+#else
+ vga_mem_writeb(opaque, addr, val & 0xff);
+ vga_mem_writeb(opaque, addr + 1, (val >> 8) & 0xff);
+ vga_mem_writeb(opaque, addr + 2, (val >> 16) & 0xff);
+ vga_mem_writeb(opaque, addr + 3, (val >> 24) & 0xff);
+#endif
+}
+
+typedef void vga_draw_glyph8_func(uint8_t *d, int linesize,
+ const uint8_t *font_ptr, int h,
+ uint32_t fgcol, uint32_t bgcol);
+typedef void vga_draw_glyph9_func(uint8_t *d, int linesize,
+ const uint8_t *font_ptr, int h,
+ uint32_t fgcol, uint32_t bgcol, int dup9);
+typedef void vga_draw_line_func(VGAState *s1, uint8_t *d,
+ const uint8_t *s, int width);
+
+static inline unsigned int rgb_to_pixel8(unsigned int r, unsigned int g, unsigned b)
+{
+ return ((r >> 5) << 5) | ((g >> 5) << 2) | (b >> 6);
+}
+
+static inline unsigned int rgb_to_pixel15(unsigned int r, unsigned int g, unsigned b)
+{
+ return ((r >> 3) << 10) | ((g >> 3) << 5) | (b >> 3);
+}
+
+static inline unsigned int rgb_to_pixel16(unsigned int r, unsigned int g, unsigned b)
+{
+ return ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);
+}
+
+static inline unsigned int rgb_to_pixel32(unsigned int r, unsigned int g, unsigned b)
+{
+ return (r << 16) | (g << 8) | b;
+}
+
+#define DEPTH 8
+#include "vga_template.h"
+
+#define DEPTH 15
+#include "vga_template.h"
+
+#define DEPTH 16
+#include "vga_template.h"
+
+#define DEPTH 32
+#include "vga_template.h"
+
+static unsigned int rgb_to_pixel8_dup(unsigned int r, unsigned int g, unsigned b)
+{
+ unsigned int col;
+ col = rgb_to_pixel8(r, g, b);
+ col |= col << 8;
+ col |= col << 16;
+ return col;
+}
+
+static unsigned int rgb_to_pixel15_dup(unsigned int r, unsigned int g, unsigned b)
+{
+ unsigned int col;
+ col = rgb_to_pixel15(r, g, b);
+ col |= col << 16;
+ return col;
+}
+
+static unsigned int rgb_to_pixel16_dup(unsigned int r, unsigned int g, unsigned b)
+{
+ unsigned int col;
+ col = rgb_to_pixel16(r, g, b);
+ col |= col << 16;
+ return col;
+}
+
+static unsigned int rgb_to_pixel32_dup(unsigned int r, unsigned int g, unsigned b)
+{
+ unsigned int col;
+ col = rgb_to_pixel32(r, g, b);
+ return col;
+}
+
+/* return true if the palette was modified */
+static int update_palette16(VGAState *s)
+{
+ int full_update, i;
+ uint32_t v, col, *palette;
+
+ full_update = 0;
+ palette = s->last_palette;
+ for(i = 0; i < 16; i++) {
+ v = s->ar[i];
+ if (s->ar[0x10] & 0x80)
+ v = ((s->ar[0x14] & 0xf) << 4) | (v & 0xf);
+ else
+ v = ((s->ar[0x14] & 0xc) << 4) | (v & 0x3f);
+ v = v * 3;
+ col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
+ c6_to_8(s->palette[v + 1]),
+ c6_to_8(s->palette[v + 2]));
+ if (col != palette[i]) {
+ full_update = 1;
+ palette[i] = col;
+ }
+ }
+ return full_update;
+}
+
+/* return true if the palette was modified */
+static int update_palette256(VGAState *s)
+{
+ int full_update, i;
+ uint32_t v, col, *palette;
+
+ full_update = 0;
+ palette = s->last_palette;
+ v = 0;
+ for(i = 0; i < 256; i++) {
+ col = s->rgb_to_pixel(c6_to_8(s->palette[v]),
+ c6_to_8(s->palette[v + 1]),
+ c6_to_8(s->palette[v + 2]));
+ if (col != palette[i]) {
+ full_update = 1;
+ palette[i] = col;
+ }
+ v += 3;
+ }
+ return full_update;
+}
+
+static void vga_get_offsets(VGAState *s,
+ uint32_t *pline_offset,
+ uint32_t *pstart_addr)
+{
+ uint32_t start_addr, line_offset;
+#ifdef CONFIG_BOCHS_VBE
+ if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
+ line_offset = s->vbe_line_offset;
+ start_addr = s->vbe_start_addr;
+ } else
+#endif
+ {
+ /* compute line_offset in bytes */
+ line_offset = s->cr[0x13];
+#ifdef CONFIG_S3VGA
+ {
+ uinr32_t v;
+ v = (s->cr[0x51] >> 4) & 3; /* S3 extension */
+ if (v == 0)
+ v = (s->cr[0x43] >> 2) & 1; /* S3 extension */
+ line_offset |= (v << 8);
+ }
+#endif
+ line_offset <<= 3;
+
+ /* starting address */
+ start_addr = s->cr[0x0d] | (s->cr[0x0c] << 8);
+#ifdef CONFIG_S3VGA
+ start_addr |= (s->cr[0x69] & 0x1f) << 16; /* S3 extension */
+#endif
+ }
+ *pline_offset = line_offset;
+ *pstart_addr = start_addr;
+}
+
+/* update start_addr and line_offset. Return TRUE if modified */
+static int update_basic_params(VGAState *s)
+{
+ int full_update;
+ uint32_t start_addr, line_offset, line_compare;
+
+ full_update = 0;
+
+ s->get_offsets(s, &line_offset, &start_addr);
+ /* line compare */
+ line_compare = s->cr[0x18] |
+ ((s->cr[0x07] & 0x10) << 4) |
+ ((s->cr[0x09] & 0x40) << 3);
+
+ if (line_offset != s->line_offset ||
+ start_addr != s->start_addr ||
+ line_compare != s->line_compare) {
+ s->line_offset = line_offset;
+ s->start_addr = start_addr;
+ s->line_compare = line_compare;
+ full_update = 1;
+ }
+ return full_update;
+}
+
+static inline int get_depth_index(int depth)
+{
+ switch(depth) {
+ default:
+ case 8:
+ return 0;
+ case 15:
+ return 1;
+ case 16:
+ return 2;
+ case 32:
+ return 3;
+ }
+}
+
+static vga_draw_glyph8_func *vga_draw_glyph8_table[4] = {
+ vga_draw_glyph8_8,
+ vga_draw_glyph8_16,
+ vga_draw_glyph8_16,
+ vga_draw_glyph8_32,
+};
+
+static vga_draw_glyph8_func *vga_draw_glyph16_table[4] = {
+ vga_draw_glyph16_8,
+ vga_draw_glyph16_16,
+ vga_draw_glyph16_16,
+ vga_draw_glyph16_32,
+};
+
+static vga_draw_glyph9_func *vga_draw_glyph9_table[4] = {
+ vga_draw_glyph9_8,
+ vga_draw_glyph9_16,
+ vga_draw_glyph9_16,
+ vga_draw_glyph9_32,
+};
+
+static const uint8_t cursor_glyph[32 * 4] = {
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+};
+
+/*
+ * Text mode update
+ * Missing:
+ * - double scan
+ * - double width
+ * - underline
+ * - flashing
+ */
+static void vga_draw_text(VGAState *s, int full_update)
+{
+ int cx, cy, cheight, cw, ch, cattr, height, width, ch_attr;
+ int cx_min, cx_max, linesize, x_incr;
+ uint32_t offset, fgcol, bgcol, v, cursor_offset;
+ uint8_t *d1, *d, *src, *s1, *dest, *cursor_ptr;
+ const uint8_t *font_ptr, *font_base[2];
+ int dup9, line_offset, depth_index;
+ uint32_t *palette;
+ uint32_t *ch_attr_ptr;
+ vga_draw_glyph8_func *vga_draw_glyph8;
+ vga_draw_glyph9_func *vga_draw_glyph9;
+
+ full_update |= update_palette16(s);
+ palette = s->last_palette;
+
+ /* compute font data address (in plane 2) */
+ v = s->sr[3];
+ offset = (((v >> 4) & 1) | ((v << 1) & 6)) * 8192 * 4 + 2;
+ if (offset != s->font_offsets[0]) {
+ s->font_offsets[0] = offset;
+ full_update = 1;
+ }
+ font_base[0] = s->vram_ptr + offset;
+
+ offset = (((v >> 5) & 1) | ((v >> 1) & 6)) * 8192 * 4 + 2;
+ font_base[1] = s->vram_ptr + offset;
+ if (offset != s->font_offsets[1]) {
+ s->font_offsets[1] = offset;
+ full_update = 1;
+ }
+ if (s->plane_updated & (1 << 2)) {
+ /* if the plane 2 was modified since the last display, it
+ indicates the font may have been modified */
+ s->plane_updated = 0;
+ full_update = 1;
+ }
+ full_update |= update_basic_params(s);
+
+ line_offset = s->line_offset;
+ s1 = s->vram_ptr + (s->start_addr * 4);
+
+ /* total width & height */
+ cheight = (s->cr[9] & 0x1f) + 1;
+ cw = 8;
+ if (!(s->sr[1] & 0x01))
+ cw = 9;
+ if (s->sr[1] & 0x08)
+ cw = 16; /* NOTE: no 18 pixel wide */
+ x_incr = cw * ((s->ds->depth + 7) >> 3);
+ width = (s->cr[0x01] + 1);
+ if (s->cr[0x06] == 100) {
+ /* ugly hack for CGA 160x100x16 - explain me the logic */
+ height = 100;
+ } else {
+ height = s->cr[0x12] |
+ ((s->cr[0x07] & 0x02) << 7) |
+ ((s->cr[0x07] & 0x40) << 3);
+ height = (height + 1) / cheight;
+ }
+ if ((height * width) > CH_ATTR_SIZE) {
+ /* better than nothing: exit if transient size is too big */
+ return;
+ }
+
+ if (width != s->last_width || height != s->last_height ||
+ cw != s->last_cw || cheight != s->last_ch) {
+ s->last_scr_width = width * cw;
+ s->last_scr_height = height * cheight;
+ dpy_resize(s->ds, s->last_scr_width, s->last_scr_height);
+ s->last_width = width;
+ s->last_height = height;
+ s->last_ch = cheight;
+ s->last_cw = cw;
+ full_update = 1;
+ }
+ cursor_offset = ((s->cr[0x0e] << 8) | s->cr[0x0f]) - s->start_addr;
+ if (cursor_offset != s->cursor_offset ||
+ s->cr[0xa] != s->cursor_start ||
+ s->cr[0xb] != s->cursor_end) {
+ /* if the cursor position changed, we update the old and new
+ chars */
+ if (s->cursor_offset < CH_ATTR_SIZE)
+ s->last_ch_attr[s->cursor_offset] = -1;
+ if (cursor_offset < CH_ATTR_SIZE)
+ s->last_ch_attr[cursor_offset] = -1;
+ s->cursor_offset = cursor_offset;
+ s->cursor_start = s->cr[0xa];
+ s->cursor_end = s->cr[0xb];
+ }
+ cursor_ptr = s->vram_ptr + (s->start_addr + cursor_offset) * 4;
+
+ depth_index = get_depth_index(s->ds->depth);
+ if (cw == 16)
+ vga_draw_glyph8 = vga_draw_glyph16_table[depth_index];
+ else
+ vga_draw_glyph8 = vga_draw_glyph8_table[depth_index];
+ vga_draw_glyph9 = vga_draw_glyph9_table[depth_index];
+
+ dest = s->ds->data;
+ linesize = s->ds->linesize;
+ ch_attr_ptr = s->last_ch_attr;
+ for(cy = 0; cy < height; cy++) {
+ d1 = dest;
+ src = s1;
+ cx_min = width;
+ cx_max = -1;
+ for(cx = 0; cx < width; cx++) {
+ ch_attr = *(uint16_t *)src;
+ if (full_update || ch_attr != *ch_attr_ptr) {
+ if (cx < cx_min)
+ cx_min = cx;
+ if (cx > cx_max)
+ cx_max = cx;
+ *ch_attr_ptr = ch_attr;
+#ifdef WORDS_BIGENDIAN
+ ch = ch_attr >> 8;
+ cattr = ch_attr & 0xff;
+#else
+ ch = ch_attr & 0xff;
+ cattr = ch_attr >> 8;
+#endif
+ font_ptr = font_base[(cattr >> 3) & 1];
+ font_ptr += 32 * 4 * ch;
+ bgcol = palette[cattr >> 4];
+ fgcol = palette[cattr & 0x0f];
+ if (cw != 9) {
+ vga_draw_glyph8(d1, linesize,
+ font_ptr, cheight, fgcol, bgcol);
+ } else {
+ dup9 = 0;
+ if (ch >= 0xb0 && ch <= 0xdf && (s->ar[0x10] & 0x04))
+ dup9 = 1;
+ vga_draw_glyph9(d1, linesize,
+ font_ptr, cheight, fgcol, bgcol, dup9);
+ }
+ if (src == cursor_ptr &&
+ !(s->cr[0x0a] & 0x20)) {
+ int line_start, line_last, h;
+ /* draw the cursor */
+ line_start = s->cr[0x0a] & 0x1f;
+ line_last = s->cr[0x0b] & 0x1f;
+ /* XXX: check that */
+ if (line_last > cheight - 1)
+ line_last = cheight - 1;
+ if (line_last >= line_start && line_start < cheight) {
+ h = line_last - line_start + 1;
+ d = d1 + linesize * line_start;
+ if (cw != 9) {
+ vga_draw_glyph8(d, linesize,
+ cursor_glyph, h, fgcol, bgcol);
+ } else {
+ vga_draw_glyph9(d, linesize,
+ cursor_glyph, h, fgcol, bgcol, 1);
+ }
+ }
+ }
+ }
+ d1 += x_incr;
+ src += 4;
+ ch_attr_ptr++;
+ }
+ if (cx_max != -1) {
+ dpy_update(s->ds, cx_min * cw, cy * cheight,
+ (cx_max - cx_min + 1) * cw, cheight);
+ }
+ dest += linesize * cheight;
+ s1 += line_offset;
+ }
+}
+
+enum {
+ VGA_DRAW_LINE2,
+ VGA_DRAW_LINE2D2,
+ VGA_DRAW_LINE4,
+ VGA_DRAW_LINE4D2,
+ VGA_DRAW_LINE8D2,
+ VGA_DRAW_LINE8,
+ VGA_DRAW_LINE15,
+ VGA_DRAW_LINE16,
+ VGA_DRAW_LINE24,
+ VGA_DRAW_LINE32,
+ VGA_DRAW_LINE_NB,
+};
+
+static vga_draw_line_func *vga_draw_line_table[4 * VGA_DRAW_LINE_NB] = {
+ vga_draw_line2_8,
+ vga_draw_line2_16,
+ vga_draw_line2_16,
+ vga_draw_line2_32,
+
+ vga_draw_line2d2_8,
+ vga_draw_line2d2_16,
+ vga_draw_line2d2_16,
+ vga_draw_line2d2_32,
+
+ vga_draw_line4_8,
+ vga_draw_line4_16,
+ vga_draw_line4_16,
+ vga_draw_line4_32,
+
+ vga_draw_line4d2_8,
+ vga_draw_line4d2_16,
+ vga_draw_line4d2_16,
+ vga_draw_line4d2_32,
+
+ vga_draw_line8d2_8,
+ vga_draw_line8d2_16,
+ vga_draw_line8d2_16,
+ vga_draw_line8d2_32,
+
+ vga_draw_line8_8,
+ vga_draw_line8_16,
+ vga_draw_line8_16,
+ vga_draw_line8_32,
+
+ vga_draw_line15_8,
+ vga_draw_line15_15,
+ vga_draw_line15_16,
+ vga_draw_line15_32,
+
+ vga_draw_line16_8,
+ vga_draw_line16_15,
+ vga_draw_line16_16,
+ vga_draw_line16_32,
+
+ vga_draw_line24_8,
+ vga_draw_line24_15,
+ vga_draw_line24_16,
+ vga_draw_line24_32,
+
+ vga_draw_line32_8,
+ vga_draw_line32_15,
+ vga_draw_line32_16,
+ vga_draw_line32_32,
+};
+
+static int vga_get_bpp(VGAState *s)
+{
+ int ret;
+#ifdef CONFIG_BOCHS_VBE
+ if (s->vbe_regs[VBE_DISPI_INDEX_ENABLE] & VBE_DISPI_ENABLED) {
+ ret = s->vbe_regs[VBE_DISPI_INDEX_BPP];
+ } else
+#endif
+ {
+ ret = 0;
+ }
+ return ret;
+}
+
+static void vga_get_resolution(VGAState *s, int *pwidth, int *pheight)
+{
+ int width, height;
+
+ width = (s->cr[0x01] + 1) * 8;
+ height = s->cr[0x12] |
+ ((s->cr[0x07] & 0x02) << 7) |
+ ((s->cr[0x07] & 0x40) << 3);
+ height = (height + 1);
+ *pwidth = width;
+ *pheight = height;
+}
+
+void vga_invalidate_scanlines(VGAState *s, int y1, int y2)
+{
+ int y;
+ if (y1 >= VGA_MAX_HEIGHT)
+ return;
+ if (y2 >= VGA_MAX_HEIGHT)
+ y2 = VGA_MAX_HEIGHT;
+ for(y = y1; y < y2; y++) {
+ s->invalidated_y_table[y >> 5] |= 1 << (y & 0x1f);
+ }
+}
+
+/*
+ * graphic modes
+ */
+static void vga_draw_graphic(VGAState *s, int full_update)
+{
+ int y1, y, update, page_min, page_max, linesize, y_start, double_scan, mask;
+ int width, height, shift_control, line_offset, page0, page1, bwidth;
+ int disp_width, multi_scan, multi_run;
+ uint8_t *d;
+ uint32_t v, addr1, addr;
+ vga_draw_line_func *vga_draw_line;
+
+ full_update |= update_basic_params(s);
+
+ s->get_resolution(s, &width, &height);
+ disp_width = width;
+
+ shift_control = (s->gr[0x05] >> 5) & 3;
+ double_scan = (s->cr[0x09] >> 7);
+ if (shift_control != 1) {
+ multi_scan = (((s->cr[0x09] & 0x1f) + 1) << double_scan) - 1;
+ } else {
+ /* in CGA modes, multi_scan is ignored */
+ /* XXX: is it correct ? */
+ multi_scan = double_scan;
+ }
+ multi_run = multi_scan;
+ if (shift_control != s->shift_control ||
+ double_scan != s->double_scan) {
+ full_update = 1;
+ s->shift_control = shift_control;
+ s->double_scan = double_scan;
+ }
+
+ if (shift_control == 0) {
+ full_update |= update_palette16(s);
+ if (s->sr[0x01] & 8) {
+ v = VGA_DRAW_LINE4D2;
+ disp_width <<= 1;
+ } else {
+ v = VGA_DRAW_LINE4;
+ }
+ } else if (shift_control == 1) {
+ full_update |= update_palette16(s);
+ if (s->sr[0x01] & 8) {
+ v = VGA_DRAW_LINE2D2;
+ disp_width <<= 1;
+ } else {
+ v = VGA_DRAW_LINE2;
+ }
+ } else {
+ switch(s->get_bpp(s)) {
+ default:
+ case 0:
+ full_update |= update_palette256(s);
+ v = VGA_DRAW_LINE8D2;
+ break;
+ case 8:
+ full_update |= update_palette256(s);
+ v = VGA_DRAW_LINE8;
+ break;
+ case 15:
+ v = VGA_DRAW_LINE15;
+ break;
+ case 16:
+ v = VGA_DRAW_LINE16;
+ break;
+ case 24:
+ v = VGA_DRAW_LINE24;
+ break;
+ case 32:
+ v = VGA_DRAW_LINE32;
+ break;
+ }
+ }
+ vga_draw_line = vga_draw_line_table[v * 4 + get_depth_index(s->ds->depth)];
+
+ if (disp_width != s->last_width ||
+ height != s->last_height) {
+ dpy_resize(s->ds, disp_width, height);
+ s->last_scr_width = disp_width;
+ s->last_scr_height = height;
+ s->last_width = disp_width;
+ s->last_height = height;
+ full_update = 1;
+ }
+ if (s->cursor_invalidate)
+ s->cursor_invalidate(s);
+
+ line_offset = s->line_offset;
+#if 0
+ printf("w=%d h=%d v=%d line_offset=%d cr[0x09]=0x%02x cr[0x17]=0x%02x linecmp=%d sr[0x01]=0x%02x\n",
+ width, height, v, line_offset, s->cr[9], s->cr[0x17], s->line_compare, s->sr[0x01]);
+#endif
+ addr1 = (s->start_addr * 4);
+ bwidth = width * 4;
+ y_start = -1;
+ page_min = 0x7fffffff;
+ page_max = -1;
+ d = s->ds->data;
+ linesize = s->ds->linesize;
+ y1 = 0;
+ for(y = 0; y < height; y++) {
+ addr = addr1;
+ if (!(s->cr[0x17] & 1)) {
+ int shift;
+ /* CGA compatibility handling */
+ shift = 14 + ((s->cr[0x17] >> 6) & 1);
+ addr = (addr & ~(1 << shift)) | ((y1 & 1) << shift);
+ }
+ if (!(s->cr[0x17] & 2)) {
+ addr = (addr & ~0x8000) | ((y1 & 2) << 14);
+ }
+ page0 = s->vram_offset + (addr & TARGET_PAGE_MASK);
+ page1 = s->vram_offset + ((addr + bwidth - 1) & TARGET_PAGE_MASK);
+ update = full_update | cpu_physical_memory_is_dirty(page0) |
+ cpu_physical_memory_is_dirty(page1);
+ if ((page1 - page0) > TARGET_PAGE_SIZE) {
+ /* if wide line, can use another page */
+ update |= cpu_physical_memory_is_dirty(page0 + TARGET_PAGE_SIZE);
+ }
+ /* explicit invalidation for the hardware cursor */
+ update |= (s->invalidated_y_table[y >> 5] >> (y & 0x1f)) & 1;
+ if (update) {
+ if (y_start < 0)
+ y_start = y;
+ if (page0 < page_min)
+ page_min = page0;
+ if (page1 > page_max)
+ page_max = page1;
+ vga_draw_line(s, d, s->vram_ptr + addr, width);
+ if (s->cursor_draw_line)
+ s->cursor_draw_line(s, d, y);
+ } else {
+ if (y_start >= 0) {
+ /* flush to display */
+ dpy_update(s->ds, 0, y_start,
+ disp_width, y - y_start);
+ y_start = -1;
+ }
+ }
+ if (!multi_run) {
+ mask = (s->cr[0x17] & 3) ^ 3;
+ if ((y1 & mask) == mask)
+ addr1 += line_offset;
+ y1++;
+ multi_run = multi_scan;
+ } else {
+ multi_run--;
+ }
+ /* line compare acts on the displayed lines */
+ if (y == s->line_compare)
+ addr1 = 0;
+ d += linesize;
+ }
+ if (y_start >= 0) {
+ /* flush to display */
+ dpy_update(s->ds, 0, y_start,
+ disp_width, y - y_start);
+ }
+ /* reset modified pages */
+ if (page_max != -1) {
+ cpu_physical_memory_reset_dirty(page_min, page_max + TARGET_PAGE_SIZE);
+ }
+ memset(s->invalidated_y_table, 0, ((height + 31) >> 5) * 4);
+}
+
+static void vga_draw_blank(VGAState *s, int full_update)
+{
+ int i, w, val;
+ uint8_t *d;
+
+ if (!full_update)
+ return;
+ if (s->last_scr_width <= 0 || s->last_scr_height <= 0)
+ return;
+ if (s->ds->depth == 8)
+ val = s->rgb_to_pixel(0, 0, 0);
+ else
+ val = 0;
+ w = s->last_scr_width * ((s->ds->depth + 7) >> 3);
+ d = s->ds->data;
+ for(i = 0; i < s->last_scr_height; i++) {
+ memset(d, val, w);
+ d += s->ds->linesize;
+ }
+ dpy_update(s->ds, 0, 0,
+ s->last_scr_width, s->last_scr_height);
+}
+
+#define GMODE_TEXT 0
+#define GMODE_GRAPH 1
+#define GMODE_BLANK 2
+
+void vga_update_display(void)
+{
+ VGAState *s = vga_state;
+ int full_update, graphic_mode;
+
+ if (s->ds->depth == 0) {
+ /* nothing to do */
+ } else {
+ switch(s->ds->depth) {
+ case 8:
+ s->rgb_to_pixel = rgb_to_pixel8_dup;
+ break;
+ case 15:
+ s->rgb_to_pixel = rgb_to_pixel15_dup;
+ break;
+ default:
+ case 16:
+ s->rgb_to_pixel = rgb_to_pixel16_dup;
+ break;
+ case 32:
+ s->rgb_to_pixel = rgb_to_pixel32_dup;
+ break;
+ }
+
+ full_update = 0;
+ if (!(s->ar_index & 0x20)) {
+ graphic_mode = GMODE_BLANK;
+ } else {
+ graphic_mode = s->gr[6] & 1;
+ }
+ if (graphic_mode != s->graphic_mode) {
+ s->graphic_mode = graphic_mode;
+ full_update = 1;
+ }
+ switch(graphic_mode) {
+ case GMODE_TEXT:
+ vga_draw_text(s, full_update);
+ break;
+ case GMODE_GRAPH:
+ vga_draw_graphic(s, full_update);
+ break;
+ case GMODE_BLANK:
+ default:
+ vga_draw_blank(s, full_update);
+ break;
+ }
+ }
+}
+
+/* force a full display refresh */
+void vga_invalidate_display(void)
+{
+ VGAState *s = vga_state;
+
+ s->last_width = -1;
+ s->last_height = -1;
+}
+
+static void vga_reset(VGAState *s)
+{
+ memset(s, 0, sizeof(VGAState));
+#ifdef CONFIG_S3VGA
+ /* chip ID for 8c968 */
+ s->cr[0x2d] = 0x88;
+ s->cr[0x2e] = 0xb0;
+ s->cr[0x2f] = 0x01; /* XXX: check revision code */
+ s->cr[0x30] = 0xe1;
+#endif
+ s->graphic_mode = -1; /* force full update */
+}
+
+static CPUReadMemoryFunc *vga_mem_read[3] = {
+ vga_mem_readb,
+ vga_mem_readw,
+ vga_mem_readl,
+};
+
+static CPUWriteMemoryFunc *vga_mem_write[3] = {
+ vga_mem_writeb,
+ vga_mem_writew,
+ vga_mem_writel,
+};
+
+static void vga_save(QEMUFile *f, void *opaque)
+{
+ VGAState *s = opaque;
+ int i;
+
+ qemu_put_be32s(f, &s->latch);
+ qemu_put_8s(f, &s->sr_index);
+ qemu_put_buffer(f, s->sr, 8);
+ qemu_put_8s(f, &s->gr_index);
+ qemu_put_buffer(f, s->gr, 16);
+ qemu_put_8s(f, &s->ar_index);
+ qemu_put_buffer(f, s->ar, 21);
+ qemu_put_be32s(f, &s->ar_flip_flop);
+ qemu_put_8s(f, &s->cr_index);
+ qemu_put_buffer(f, s->cr, 256);
+ qemu_put_8s(f, &s->msr);
+ qemu_put_8s(f, &s->fcr);
+ qemu_put_8s(f, &s->st00);
+ qemu_put_8s(f, &s->st01);
+
+ qemu_put_8s(f, &s->dac_state);
+ qemu_put_8s(f, &s->dac_sub_index);
+ qemu_put_8s(f, &s->dac_read_index);
+ qemu_put_8s(f, &s->dac_write_index);
+ qemu_put_buffer(f, s->dac_cache, 3);
+ qemu_put_buffer(f, s->palette, 768);
+
+ qemu_put_be32s(f, &s->bank_offset);
+#ifdef CONFIG_BOCHS_VBE
+ qemu_put_byte(f, 1);
+ qemu_put_be16s(f, &s->vbe_index);
+ for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
+ qemu_put_be16s(f, &s->vbe_regs[i]);
+ qemu_put_be32s(f, &s->vbe_start_addr);
+ qemu_put_be32s(f, &s->vbe_line_offset);
+ qemu_put_be32s(f, &s->vbe_bank_mask);
+#else
+ qemu_put_byte(f, 0);
+#endif
+}
+
+static int vga_load(QEMUFile *f, void *opaque, int version_id)
+{
+ VGAState *s = opaque;
+ int is_vbe, i;
+
+ if (version_id != 1)
+ return -EINVAL;
+
+ qemu_get_be32s(f, &s->latch);
+ qemu_get_8s(f, &s->sr_index);
+ qemu_get_buffer(f, s->sr, 8);
+ qemu_get_8s(f, &s->gr_index);
+ qemu_get_buffer(f, s->gr, 16);
+ qemu_get_8s(f, &s->ar_index);
+ qemu_get_buffer(f, s->ar, 21);
+ qemu_get_be32s(f, &s->ar_flip_flop);
+ qemu_get_8s(f, &s->cr_index);
+ qemu_get_buffer(f, s->cr, 256);
+ qemu_get_8s(f, &s->msr);
+ qemu_get_8s(f, &s->fcr);
+ qemu_get_8s(f, &s->st00);
+ qemu_get_8s(f, &s->st01);
+
+ qemu_get_8s(f, &s->dac_state);
+ qemu_get_8s(f, &s->dac_sub_index);
+ qemu_get_8s(f, &s->dac_read_index);
+ qemu_get_8s(f, &s->dac_write_index);
+ qemu_get_buffer(f, s->dac_cache, 3);
+ qemu_get_buffer(f, s->palette, 768);
+
+ qemu_get_be32s(f, &s->bank_offset);
+ is_vbe = qemu_get_byte(f);
+#ifdef CONFIG_BOCHS_VBE
+ if (!is_vbe)
+ return -EINVAL;
+ qemu_get_be16s(f, &s->vbe_index);
+ for(i = 0; i < VBE_DISPI_INDEX_NB; i++)
+ qemu_get_be16s(f, &s->vbe_regs[i]);
+ qemu_get_be32s(f, &s->vbe_start_addr);
+ qemu_get_be32s(f, &s->vbe_line_offset);
+ qemu_get_be32s(f, &s->vbe_bank_mask);
+#else
+ if (is_vbe)
+ return -EINVAL;
+#endif
+
+ /* force refresh */
+ s->graphic_mode = -1;
+ return 0;
+}
+
+static void vga_map(PCIDevice *pci_dev, int region_num,
+ uint32_t addr, uint32_t size, int type)
+{
+ VGAState *s = vga_state;
+
+ cpu_register_physical_memory(addr, s->vram_size, s->vram_offset);
+}
+
+/* do the same job as vgabios before vgabios get ready */
+void vga_bios_init(VGAState *s)
+{
+ uint8_t palette_model[192] = {
+ 0, 0, 0, 0, 0, 170, 0, 170, 0, 0, 170, 170, 170, 0, 0, 170,
+ 0, 170, 170, 85, 0, 170, 170, 170, 85, 85, 85, 85, 85, 255, 85, 255,
+ 85, 85, 255, 255, 255, 85, 85, 255, 85, 255, 255, 255, 85, 255, 255, 255,
+ 0, 21, 0, 0, 21, 42, 0, 63, 0, 0, 63, 42, 42, 21, 0, 42,
+ 21, 42, 42, 63, 0, 42, 63, 42, 0, 21, 21, 0, 21, 63, 0, 63,
+ 21, 0, 63, 63, 42, 21, 21, 42, 21, 63, 42, 63, 21, 42, 63, 63,
+ 21, 0, 0, 21, 0, 42, 21, 42, 0, 21, 42, 42, 63, 0, 0, 63,
+ 0, 42, 63, 42, 0, 63, 42, 42, 21, 0, 21, 21, 0, 63, 21, 42,
+ 21, 21, 42, 63, 63, 0, 21, 63, 0, 63, 63, 42, 21, 63, 42, 63,
+ 21, 21, 0, 21, 21, 42, 21, 63, 0, 21, 63, 42, 63, 21, 0, 63,
+ 21, 42, 63, 63, 0, 63, 63, 42, 21, 21, 21, 21, 21, 63, 21, 63,
+ 21, 21, 63, 63, 63, 21, 21, 63, 21, 63, 63, 63, 21, 63, 63, 63
+ };
+
+ s->latch = 0;
+
+ s->sr_index = 3;
+ s->sr[0] = 3;
+ s->sr[1] = 0;
+ s->sr[2] = 3;
+ s->sr[3] = 0;
+ s->sr[4] = 2;
+ s->sr[5] = 0;
+ s->sr[6] = 0;
+ s->sr[7] = 0;
+
+ s->gr_index = 5;
+ s->gr[0] = 0;
+ s->gr[1] = 0;
+ s->gr[2] = 0;
+ s->gr[3] = 0;
+ s->gr[4] = 0;
+ s->gr[5] = 16;
+ s->gr[6] = 14;
+ s->gr[7] = 15;
+ s->gr[8] = 255;
+
+ /*changed by out 0x03c0*/
+ s->ar_index = 32;
+ s->ar[0] = 0;
+ s->ar[1] = 1;
+ s->ar[2] = 2;
+ s->ar[3] = 3;
+ s->ar[4] = 4;
+ s->ar[5] = 5;
+ s->ar[6] = 6;
+ s->ar[7] = 7;
+ s->ar[8] = 8;
+ s->ar[9] = 9;
+ s->ar[10] = 10;
+ s->ar[11] = 11;
+ s->ar[12] = 12;
+ s->ar[13] = 13;
+ s->ar[14] = 14;
+ s->ar[15] = 15;
+ s->ar[16] = 12;
+ s->ar[17] = 0;
+ s->ar[18] = 15;
+ s->ar[19] = 8;
+ s->ar[20] = 0;
+
+ s->ar_flip_flop = 1;
+
+ s->cr_index = 15;
+ s->cr[0] = 95;
+ s->cr[1] = 79;
+ s->cr[2] = 80;
+ s->cr[3] = 130;
+ s->cr[4] = 85;
+ s->cr[5] = 129;
+ s->cr[6] = 191;
+ s->cr[7] = 31;
+ s->cr[8] = 0;
+ s->cr[9] = 79;
+ s->cr[10] = 14;
+ s->cr[11] = 15;
+ s->cr[12] = 0;
+ s->cr[13] = 0;
+ s->cr[14] = 5;
+ s->cr[15] = 160;
+ s->cr[16] = 156;
+ s->cr[17] = 142;
+ s->cr[18] = 143;
+ s->cr[19] = 40;
+ s->cr[20] = 31;
+ s->cr[21] = 150;
+ s->cr[22] = 185;
+ s->cr[23] = 163;
+ s->cr[24] = 255;
+
+ s->msr = 103;
+ s->fcr = 0;
+ s->st00 = 0;
+ s->st01 = 0;
+
+ /*dac_* & platte will be initialized by os through out 0x03c8 & out 0c03c9(1:3) */
+ s->dac_state = 0;
+ s->dac_sub_index = 0;
+ s->dac_read_index = 0;
+ s->dac_write_index = 16;
+ s->dac_cache[0] = 255;
+ s->dac_cache[1] = 255;
+ s->dac_cache[2] = 255;
+
+ /*platte*/
+ memcpy(s->palette, palette_model, 192);
+
+ s->bank_offset= 0;
+ s->graphic_mode = -1;
+
+ /* TODO:add vbe support if enable it */
+
+ FILE *qemuf = fopen("/etc/xen/qemu-vgaram-bin", "rb");
+ if (!qemuf) {
+ fprintf(logfile, "open qemu vgaram binary failed!\n");
+ } else {
+ /*load vram contents, else vga console can't boot */
+ qemu_get_buffer(qemuf, s->vram_ptr, 256*1024);
+
+ fclose(qemuf);
+ }
+
+}
+
+void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base,
+ unsigned long vga_ram_offset, int vga_ram_size)
+{
+ int i, j, v, b;
+
+ for(i = 0;i < 256; i++) {
+ v = 0;
+ for(j = 0; j < 8; j++) {
+ v |= ((i >> j) & 1) << (j * 4);
+ }
+ expand4[i] = v;
+
+ v = 0;
+ for(j = 0; j < 4; j++) {
+ v |= ((i >> (2 * j)) & 3) << (j * 4);
+ }
+ expand2[i] = v;
+ }
+ for(i = 0; i < 16; i++) {
+ v = 0;
+ for(j = 0; j < 4; j++) {
+ b = ((i >> j) & 1);
+ v |= b << (2 * j);
+ v |= b << (2 * j + 1);
+ }
+ expand4to8[i] = v;
+ }
+
+ vga_reset(s);
+
+ /* qemu's vga mem is not detached from phys_ram_base and can cause DM abort
+ * when guest write vga mem, so allocate a new one */
+ s->vram_ptr = qemu_mallocz(256 * 1024);
+
+ s->vram_offset = vga_ram_offset;
+ s->vram_size = vga_ram_size;
+ s->ds = ds;
+ s->get_bpp = vga_get_bpp;
+ s->get_offsets = vga_get_offsets;
+ s->get_resolution = vga_get_resolution;
+ /* XXX: currently needed for display */
+ vga_state = s;
+}
+
+
+int vga_initialize(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
+ unsigned long vga_ram_offset, int vga_ram_size)
+{
+ VGAState *s;
+
+ s = qemu_mallocz(sizeof(VGAState));
+ if (!s)
+ return -1;
+
+ vga_common_init(s, ds, vga_ram_base, vga_ram_offset, vga_ram_size);
+
+ register_savevm("vga", 0, 1, vga_save, vga_load, s);
+
+ register_ioport_write(0x3c0, 16, 1, vga_ioport_write, s);
+
+ register_ioport_write(0x3b4, 2, 1, vga_ioport_write, s);
+ register_ioport_write(0x3d4, 2, 1, vga_ioport_write, s);
+ register_ioport_write(0x3ba, 1, 1, vga_ioport_write, s);
+ register_ioport_write(0x3da, 1, 1, vga_ioport_write, s);
+
+ register_ioport_read(0x3c0, 16, 1, vga_ioport_read, s);
+
+ register_ioport_read(0x3b4, 2, 1, vga_ioport_read, s);
+ register_ioport_read(0x3d4, 2, 1, vga_ioport_read, s);
+ register_ioport_read(0x3ba, 1, 1, vga_ioport_read, s);
+ register_ioport_read(0x3da, 1, 1, vga_ioport_read, s);
+ s->bank_offset = 0;
+
+#ifdef CONFIG_BOCHS_VBE
+ s->vbe_regs[VBE_DISPI_INDEX_ID] = VBE_DISPI_ID0;
+ s->vbe_bank_mask = ((s->vram_size >> 16) - 1);
+#if defined (TARGET_I386)
+ register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
+ register_ioport_read(0x1cf, 1, 2, vbe_ioport_read_data, s);
+
+ register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
+ register_ioport_write(0x1cf, 1, 2, vbe_ioport_write_data, s);
+
+ /* old Bochs IO ports */
+ register_ioport_read(0xff80, 1, 2, vbe_ioport_read_index, s);
+ register_ioport_read(0xff81, 1, 2, vbe_ioport_read_data, s);
+
+ register_ioport_write(0xff80, 1, 2, vbe_ioport_write_index, s);
+ register_ioport_write(0xff81, 1, 2, vbe_ioport_write_data, s);
+#else
+ register_ioport_read(0x1ce, 1, 2, vbe_ioport_read_index, s);
+ register_ioport_read(0x1d0, 1, 2, vbe_ioport_read_data, s);
+
+ register_ioport_write(0x1ce, 1, 2, vbe_ioport_write_index, s);
+ register_ioport_write(0x1d0, 1, 2, vbe_ioport_write_data, s);
+#endif
+#endif /* CONFIG_BOCHS_VBE */
+
+ vga_io_memory = cpu_register_io_memory(0, vga_mem_read, vga_mem_write, s);
+ cpu_register_physical_memory(isa_mem_base + 0x000a0000, 0x20000,
+ vga_io_memory);
+
+ if (bus) {
+ PCIDevice *d;
+ uint8_t *pci_conf;
+
+ d = pci_register_device(bus, "VGA",
+ sizeof(PCIDevice),
+ -1, NULL, NULL);
+ pci_conf = d->config;
+ pci_conf[0x00] = 0x34; // dummy VGA (same as Bochs ID)
+ pci_conf[0x01] = 0x12;
+ pci_conf[0x02] = 0x11;
+ pci_conf[0x03] = 0x11;
+ pci_conf[0x0a] = 0x00; // VGA controller
+ pci_conf[0x0b] = 0x03;
+ pci_conf[0x0e] = 0x00; // header_type
+
+ /* XXX: vga_ram_size must be a power of two */
+ pci_register_io_region(d, 0, vga_ram_size,
+ PCI_ADDRESS_SPACE_MEM_PREFETCH, vga_map);
+ } else {
+#ifdef CONFIG_BOCHS_VBE
+ /* XXX: use optimized standard vga accesses */
+ cpu_register_physical_memory(VBE_DISPI_LFB_PHYSICAL_ADDRESS,
+ vga_ram_size, vga_ram_offset);
+#endif
+ }
+
+ vga_bios_init(s);
+ return 0;
+}
+
+/********************************************************/
+/* vga screen dump */
+
+static int vga_save_w, vga_save_h;
+
+static void vga_save_dpy_update(DisplayState *s,
+ int x, int y, int w, int h)
+{
+}
+
+static void vga_save_dpy_resize(DisplayState *s, int w, int h)
+{
+ s->linesize = w * 4;
+ s->data = qemu_malloc(h * s->linesize);
+ vga_save_w = w;
+ vga_save_h = h;
+}
+
+static void vga_save_dpy_refresh(DisplayState *s)
+{
+}
+
+static int ppm_save(const char *filename, uint8_t *data,
+ int w, int h, int linesize)
+{
+ FILE *f;
+ uint8_t *d, *d1;
+ unsigned int v;
+ int y, x;
+
+ f = fopen(filename, "wb");
+ if (!f)
+ return -1;
+ fprintf(f, "P6\n%d %d\n%d\n",
+ w, h, 255);
+ d1 = data;
+ for(y = 0; y < h; y++) {
+ d = d1;
+ for(x = 0; x < w; x++) {
+ v = *(uint32_t *)d;
+ fputc((v >> 16) & 0xff, f);
+ fputc((v >> 8) & 0xff, f);
+ fputc((v) & 0xff, f);
+ d += 4;
+ }
+ d1 += linesize;
+ }
+ fclose(f);
+ return 0;
+}
+
+/* save the vga display in a PPM image even if no display is
+ available */
+void vga_screen_dump(const char *filename)
+{
+ VGAState *s = vga_state;
+ DisplayState *saved_ds, ds1, *ds = &ds1;
+
+ /* XXX: this is a little hackish */
+ vga_invalidate_display();
+ saved_ds = s->ds;
+
+ memset(ds, 0, sizeof(DisplayState));
+ ds->dpy_update = vga_save_dpy_update;
+ ds->dpy_resize = vga_save_dpy_resize;
+ ds->dpy_refresh = vga_save_dpy_refresh;
+ ds->depth = 32;
+
+ s->ds = ds;
+ s->graphic_mode = -1;
+ vga_update_display();
+
+ if (ds->data) {
+ ppm_save(filename, ds->data, vga_save_w, vga_save_h,
+ s->ds->linesize);
+ qemu_free(ds->data);
+ }
+ s->ds = saved_ds;
+}
--- /dev/null
+/*
+ * QEMU internal VGA defines.
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#define MSR_COLOR_EMULATION 0x01
+#define MSR_PAGE_SELECT 0x20
+
+#define ST01_V_RETRACE 0x08
+#define ST01_DISP_ENABLE 0x01
+
+/* bochs VBE support */
+//#define CONFIG_BOCHS_VBE
+
+#define VBE_DISPI_MAX_XRES 1024
+#define VBE_DISPI_MAX_YRES 768
+
+#define VBE_DISPI_INDEX_ID 0x0
+#define VBE_DISPI_INDEX_XRES 0x1
+#define VBE_DISPI_INDEX_YRES 0x2
+#define VBE_DISPI_INDEX_BPP 0x3
+#define VBE_DISPI_INDEX_ENABLE 0x4
+#define VBE_DISPI_INDEX_BANK 0x5
+#define VBE_DISPI_INDEX_VIRT_WIDTH 0x6
+#define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7
+#define VBE_DISPI_INDEX_X_OFFSET 0x8
+#define VBE_DISPI_INDEX_Y_OFFSET 0x9
+#define VBE_DISPI_INDEX_NB 0xa
+
+#define VBE_DISPI_ID0 0xB0C0
+#define VBE_DISPI_ID1 0xB0C1
+#define VBE_DISPI_ID2 0xB0C2
+
+#define VBE_DISPI_DISABLED 0x00
+#define VBE_DISPI_ENABLED 0x01
+#define VBE_DISPI_LFB_ENABLED 0x40
+#define VBE_DISPI_NOCLEARMEM 0x80
+
+#define VBE_DISPI_LFB_PHYSICAL_ADDRESS 0xE0000000
+
+#ifdef CONFIG_BOCHS_VBE
+
+#define VGA_STATE_COMMON_BOCHS_VBE \
+ uint16_t vbe_index; \
+ uint16_t vbe_regs[VBE_DISPI_INDEX_NB]; \
+ uint32_t vbe_start_addr; \
+ uint32_t vbe_line_offset; \
+ uint32_t vbe_bank_mask;
+
+#else
+
+#define VGA_STATE_COMMON_BOCHS_VBE
+
+#endif /* !CONFIG_BOCHS_VBE */
+
+#define CH_ATTR_SIZE (160 * 100)
+#define VGA_MAX_HEIGHT 1024
+
+#define VGA_STATE_COMMON \
+ uint8_t *vram_ptr; \
+ unsigned long vram_offset; \
+ unsigned int vram_size; \
+ uint32_t latch; \
+ uint8_t sr_index; \
+ uint8_t sr[256]; \
+ uint8_t gr_index; \
+ uint8_t gr[256]; \
+ uint8_t ar_index; \
+ uint8_t ar[21]; \
+ int ar_flip_flop; \
+ uint8_t cr_index; \
+ uint8_t cr[256]; /* CRT registers */ \
+ uint8_t msr; /* Misc Output Register */ \
+ uint8_t fcr; /* Feature Control Register */ \
+ uint8_t st00; /* status 0 */ \
+ uint8_t st01; /* status 1 */ \
+ uint8_t dac_state; \
+ uint8_t dac_sub_index; \
+ uint8_t dac_read_index; \
+ uint8_t dac_write_index; \
+ uint8_t dac_cache[3]; /* used when writing */ \
+ uint8_t palette[768]; \
+ int32_t bank_offset; \
+ int (*get_bpp)(struct VGAState *s); \
+ void (*get_offsets)(struct VGAState *s, \
+ uint32_t *pline_offset, \
+ uint32_t *pstart_addr); \
+ void (*get_resolution)(struct VGAState *s, \
+ int *pwidth, \
+ int *pheight); \
+ VGA_STATE_COMMON_BOCHS_VBE \
+ /* display refresh support */ \
+ DisplayState *ds; \
+ uint32_t font_offsets[2]; \
+ int graphic_mode; \
+ uint8_t shift_control; \
+ uint8_t double_scan; \
+ uint32_t line_offset; \
+ uint32_t line_compare; \
+ uint32_t start_addr; \
+ uint32_t plane_updated; \
+ uint8_t last_cw, last_ch; \
+ uint32_t last_width, last_height; /* in chars or pixels */ \
+ uint32_t last_scr_width, last_scr_height; /* in pixels */ \
+ uint8_t cursor_start, cursor_end; \
+ uint32_t cursor_offset; \
+ unsigned int (*rgb_to_pixel)(unsigned int r, \
+ unsigned int g, unsigned b); \
+ /* hardware mouse cursor support */ \
+ uint32_t invalidated_y_table[VGA_MAX_HEIGHT / 32]; \
+ void (*cursor_invalidate)(struct VGAState *s); \
+ void (*cursor_draw_line)(struct VGAState *s, uint8_t *d, int y); \
+ /* tell for each page if it has been updated since the last time */ \
+ uint32_t last_palette[256]; \
+ uint32_t last_ch_attr[CH_ATTR_SIZE]; /* XXX: make it dynamic */
+
+
+typedef struct VGAState {
+ VGA_STATE_COMMON
+} VGAState;
+
+static inline int c6_to_8(int v)
+{
+ int b;
+ v &= 0x3f;
+ b = v & 1;
+ return (v << 2) | (b << 1) | b;
+}
+
+void vga_common_init(VGAState *s, DisplayState *ds, uint8_t *vga_ram_base,
+ unsigned long vga_ram_offset, int vga_ram_size);
+uint32_t vga_mem_readb(void *opaque, target_phys_addr_t addr);
+void vga_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val);
+void vga_invalidate_scanlines(VGAState *s, int y1, int y2);
+
+void vga_draw_cursor_line_8(uint8_t *d1, const uint8_t *src1,
+ int poffset, int w,
+ unsigned int color0, unsigned int color1,
+ unsigned int color_xor);
+void vga_draw_cursor_line_16(uint8_t *d1, const uint8_t *src1,
+ int poffset, int w,
+ unsigned int color0, unsigned int color1,
+ unsigned int color_xor);
+void vga_draw_cursor_line_32(uint8_t *d1, const uint8_t *src1,
+ int poffset, int w,
+ unsigned int color0, unsigned int color1,
+ unsigned int color_xor);
+
+extern const uint8_t sr_mask[8];
+extern const uint8_t gr_mask[16];
--- /dev/null
+/*
+ * QEMU VGA Emulator templates
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#if DEPTH == 8
+#define BPP 1
+#define PIXEL_TYPE uint8_t
+#elif DEPTH == 15 || DEPTH == 16
+#define BPP 2
+#define PIXEL_TYPE uint16_t
+#elif DEPTH == 32
+#define BPP 4
+#define PIXEL_TYPE uint32_t
+#else
+#error unsupport depth
+#endif
+
+#if DEPTH != 15
+
+static inline void glue(vga_draw_glyph_line_, DEPTH)(uint8_t *d,
+ uint32_t font_data,
+ uint32_t xorcol,
+ uint32_t bgcol)
+{
+#if BPP == 1
+ ((uint32_t *)d)[0] = (dmask16[(font_data >> 4)] & xorcol) ^ bgcol;
+ ((uint32_t *)d)[1] = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol;
+#elif BPP == 2
+ ((uint32_t *)d)[0] = (dmask4[(font_data >> 6)] & xorcol) ^ bgcol;
+ ((uint32_t *)d)[1] = (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol;
+ ((uint32_t *)d)[2] = (dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol;
+ ((uint32_t *)d)[3] = (dmask4[(font_data >> 0) & 3] & xorcol) ^ bgcol;
+#else
+ ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol;
+ ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol;
+ ((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol;
+ ((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol;
+ ((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol;
+ ((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol;
+ ((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol;
+ ((uint32_t *)d)[7] = (-((font_data >> 0) & 1) & xorcol) ^ bgcol;
+#endif
+}
+
+static void glue(vga_draw_glyph8_, DEPTH)(uint8_t *d, int linesize,
+ const uint8_t *font_ptr, int h,
+ uint32_t fgcol, uint32_t bgcol)
+{
+ uint32_t font_data, xorcol;
+
+ xorcol = bgcol ^ fgcol;
+ do {
+ font_data = font_ptr[0];
+ glue(vga_draw_glyph_line_, DEPTH)(d, font_data, xorcol, bgcol);
+ font_ptr += 4;
+ d += linesize;
+ } while (--h);
+}
+
+static void glue(vga_draw_glyph16_, DEPTH)(uint8_t *d, int linesize,
+ const uint8_t *font_ptr, int h,
+ uint32_t fgcol, uint32_t bgcol)
+{
+ uint32_t font_data, xorcol;
+
+ xorcol = bgcol ^ fgcol;
+ do {
+ font_data = font_ptr[0];
+ glue(vga_draw_glyph_line_, DEPTH)(d,
+ expand4to8[font_data >> 4],
+ xorcol, bgcol);
+ glue(vga_draw_glyph_line_, DEPTH)(d + 8 * BPP,
+ expand4to8[font_data & 0x0f],
+ xorcol, bgcol);
+ font_ptr += 4;
+ d += linesize;
+ } while (--h);
+}
+
+static void glue(vga_draw_glyph9_, DEPTH)(uint8_t *d, int linesize,
+ const uint8_t *font_ptr, int h,
+ uint32_t fgcol, uint32_t bgcol, int dup9)
+{
+ uint32_t font_data, xorcol, v;
+
+ xorcol = bgcol ^ fgcol;
+ do {
+ font_data = font_ptr[0];
+#if BPP == 1
+ cpu_to_32wu((uint32_t *)d, (dmask16[(font_data >> 4)] & xorcol) ^ bgcol);
+ v = (dmask16[(font_data >> 0) & 0xf] & xorcol) ^ bgcol;
+ cpu_to_32wu(((uint32_t *)d)+1, v);
+ if (dup9)
+ ((uint8_t *)d)[8] = v >> (24 * (1 - BIG));
+ else
+ ((uint8_t *)d)[8] = bgcol;
+
+#elif BPP == 2
+ cpu_to_32wu(((uint32_t *)d)+0, (dmask4[(font_data >> 6)] & xorcol) ^ bgcol);
+ cpu_to_32wu(((uint32_t *)d)+1, (dmask4[(font_data >> 4) & 3] & xorcol) ^ bgcol);
+ cpu_to_32wu(((uint32_t *)d)+2, (dmask4[(font_data >> 2) & 3] & xorcol) ^ bgcol);
+ v = (dmask4[(font_data >> 0) & 3] & xorcol) ^ bgcol;
+ cpu_to_32wu(((uint32_t *)d)+3, v);
+ if (dup9)
+ ((uint16_t *)d)[8] = v >> (16 * (1 - BIG));
+ else
+ ((uint16_t *)d)[8] = bgcol;
+#else
+ ((uint32_t *)d)[0] = (-((font_data >> 7)) & xorcol) ^ bgcol;
+ ((uint32_t *)d)[1] = (-((font_data >> 6) & 1) & xorcol) ^ bgcol;
+ ((uint32_t *)d)[2] = (-((font_data >> 5) & 1) & xorcol) ^ bgcol;
+ ((uint32_t *)d)[3] = (-((font_data >> 4) & 1) & xorcol) ^ bgcol;
+ ((uint32_t *)d)[4] = (-((font_data >> 3) & 1) & xorcol) ^ bgcol;
+ ((uint32_t *)d)[5] = (-((font_data >> 2) & 1) & xorcol) ^ bgcol;
+ ((uint32_t *)d)[6] = (-((font_data >> 1) & 1) & xorcol) ^ bgcol;
+ v = (-((font_data >> 0) & 1) & xorcol) ^ bgcol;
+ ((uint32_t *)d)[7] = v;
+ if (dup9)
+ ((uint32_t *)d)[8] = v;
+ else
+ ((uint32_t *)d)[8] = bgcol;
+#endif
+ font_ptr += 4;
+ d += linesize;
+ } while (--h);
+}
+
+/*
+ * 4 color mode
+ */
+static void glue(vga_draw_line2_, DEPTH)(VGAState *s1, uint8_t *d,
+ const uint8_t *s, int width)
+{
+ uint32_t plane_mask, *palette, data, v;
+ int x;
+
+ palette = s1->last_palette;
+ plane_mask = mask16[s1->ar[0x12] & 0xf];
+ width >>= 3;
+ for(x = 0; x < width; x++) {
+ data = ((uint32_t *)s)[0];
+ data &= plane_mask;
+ v = expand2[GET_PLANE(data, 0)];
+ v |= expand2[GET_PLANE(data, 2)] << 2;
+ ((PIXEL_TYPE *)d)[0] = palette[v >> 12];
+ ((PIXEL_TYPE *)d)[1] = palette[(v >> 8) & 0xf];
+ ((PIXEL_TYPE *)d)[2] = palette[(v >> 4) & 0xf];
+ ((PIXEL_TYPE *)d)[3] = palette[(v >> 0) & 0xf];
+
+ v = expand2[GET_PLANE(data, 1)];
+ v |= expand2[GET_PLANE(data, 3)] << 2;
+ ((PIXEL_TYPE *)d)[4] = palette[v >> 12];
+ ((PIXEL_TYPE *)d)[5] = palette[(v >> 8) & 0xf];
+ ((PIXEL_TYPE *)d)[6] = palette[(v >> 4) & 0xf];
+ ((PIXEL_TYPE *)d)[7] = palette[(v >> 0) & 0xf];
+ d += BPP * 8;
+ s += 4;
+ }
+}
+
+#if BPP == 1
+#define PUT_PIXEL2(d, n, v) ((uint16_t *)d)[(n)] = (v)
+#elif BPP == 2
+#define PUT_PIXEL2(d, n, v) ((uint32_t *)d)[(n)] = (v)
+#else
+#define PUT_PIXEL2(d, n, v) \
+((uint32_t *)d)[2*(n)] = ((uint32_t *)d)[2*(n)+1] = (v)
+#endif
+
+/*
+ * 4 color mode, dup2 horizontal
+ */
+static void glue(vga_draw_line2d2_, DEPTH)(VGAState *s1, uint8_t *d,
+ const uint8_t *s, int width)
+{
+ uint32_t plane_mask, *palette, data, v;
+ int x;
+
+ palette = s1->last_palette;
+ plane_mask = mask16[s1->ar[0x12] & 0xf];
+ width >>= 3;
+ for(x = 0; x < width; x++) {
+ data = ((uint32_t *)s)[0];
+ data &= plane_mask;
+ v = expand2[GET_PLANE(data, 0)];
+ v |= expand2[GET_PLANE(data, 2)] << 2;
+ PUT_PIXEL2(d, 0, palette[v >> 12]);
+ PUT_PIXEL2(d, 1, palette[(v >> 8) & 0xf]);
+ PUT_PIXEL2(d, 2, palette[(v >> 4) & 0xf]);
+ PUT_PIXEL2(d, 3, palette[(v >> 0) & 0xf]);
+
+ v = expand2[GET_PLANE(data, 1)];
+ v |= expand2[GET_PLANE(data, 3)] << 2;
+ PUT_PIXEL2(d, 4, palette[v >> 12]);
+ PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]);
+ PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]);
+ PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]);
+ d += BPP * 16;
+ s += 4;
+ }
+}
+
+/*
+ * 16 color mode
+ */
+static void glue(vga_draw_line4_, DEPTH)(VGAState *s1, uint8_t *d,
+ const uint8_t *s, int width)
+{
+ uint32_t plane_mask, data, v, *palette;
+ int x;
+
+ palette = s1->last_palette;
+ plane_mask = mask16[s1->ar[0x12] & 0xf];
+ width >>= 3;
+ for(x = 0; x < width; x++) {
+ data = ((uint32_t *)s)[0];
+ data &= plane_mask;
+ v = expand4[GET_PLANE(data, 0)];
+ v |= expand4[GET_PLANE(data, 1)] << 1;
+ v |= expand4[GET_PLANE(data, 2)] << 2;
+ v |= expand4[GET_PLANE(data, 3)] << 3;
+ ((PIXEL_TYPE *)d)[0] = palette[v >> 28];
+ ((PIXEL_TYPE *)d)[1] = palette[(v >> 24) & 0xf];
+ ((PIXEL_TYPE *)d)[2] = palette[(v >> 20) & 0xf];
+ ((PIXEL_TYPE *)d)[3] = palette[(v >> 16) & 0xf];
+ ((PIXEL_TYPE *)d)[4] = palette[(v >> 12) & 0xf];
+ ((PIXEL_TYPE *)d)[5] = palette[(v >> 8) & 0xf];
+ ((PIXEL_TYPE *)d)[6] = palette[(v >> 4) & 0xf];
+ ((PIXEL_TYPE *)d)[7] = palette[(v >> 0) & 0xf];
+ d += BPP * 8;
+ s += 4;
+ }
+}
+
+/*
+ * 16 color mode, dup2 horizontal
+ */
+static void glue(vga_draw_line4d2_, DEPTH)(VGAState *s1, uint8_t *d,
+ const uint8_t *s, int width)
+{
+ uint32_t plane_mask, data, v, *palette;
+ int x;
+
+ palette = s1->last_palette;
+ plane_mask = mask16[s1->ar[0x12] & 0xf];
+ width >>= 3;
+ for(x = 0; x < width; x++) {
+ data = ((uint32_t *)s)[0];
+ data &= plane_mask;
+ v = expand4[GET_PLANE(data, 0)];
+ v |= expand4[GET_PLANE(data, 1)] << 1;
+ v |= expand4[GET_PLANE(data, 2)] << 2;
+ v |= expand4[GET_PLANE(data, 3)] << 3;
+ PUT_PIXEL2(d, 0, palette[v >> 28]);
+ PUT_PIXEL2(d, 1, palette[(v >> 24) & 0xf]);
+ PUT_PIXEL2(d, 2, palette[(v >> 20) & 0xf]);
+ PUT_PIXEL2(d, 3, palette[(v >> 16) & 0xf]);
+ PUT_PIXEL2(d, 4, palette[(v >> 12) & 0xf]);
+ PUT_PIXEL2(d, 5, palette[(v >> 8) & 0xf]);
+ PUT_PIXEL2(d, 6, palette[(v >> 4) & 0xf]);
+ PUT_PIXEL2(d, 7, palette[(v >> 0) & 0xf]);
+ d += BPP * 16;
+ s += 4;
+ }
+}
+
+/*
+ * 256 color mode, double pixels
+ *
+ * XXX: add plane_mask support (never used in standard VGA modes)
+ */
+static void glue(vga_draw_line8d2_, DEPTH)(VGAState *s1, uint8_t *d,
+ const uint8_t *s, int width)
+{
+ uint32_t *palette;
+ int x;
+
+ palette = s1->last_palette;
+ width >>= 3;
+ for(x = 0; x < width; x++) {
+ PUT_PIXEL2(d, 0, palette[s[0]]);
+ PUT_PIXEL2(d, 1, palette[s[1]]);
+ PUT_PIXEL2(d, 2, palette[s[2]]);
+ PUT_PIXEL2(d, 3, palette[s[3]]);
+ d += BPP * 8;
+ s += 4;
+ }
+}
+
+/*
+ * standard 256 color mode
+ *
+ * XXX: add plane_mask support (never used in standard VGA modes)
+ */
+static void glue(vga_draw_line8_, DEPTH)(VGAState *s1, uint8_t *d,
+ const uint8_t *s, int width)
+{
+ uint32_t *palette;
+ int x;
+
+ palette = s1->last_palette;
+ width >>= 3;
+ for(x = 0; x < width; x++) {
+ ((PIXEL_TYPE *)d)[0] = palette[s[0]];
+ ((PIXEL_TYPE *)d)[1] = palette[s[1]];
+ ((PIXEL_TYPE *)d)[2] = palette[s[2]];
+ ((PIXEL_TYPE *)d)[3] = palette[s[3]];
+ ((PIXEL_TYPE *)d)[4] = palette[s[4]];
+ ((PIXEL_TYPE *)d)[5] = palette[s[5]];
+ ((PIXEL_TYPE *)d)[6] = palette[s[6]];
+ ((PIXEL_TYPE *)d)[7] = palette[s[7]];
+ d += BPP * 8;
+ s += 8;
+ }
+}
+
+#endif /* DEPTH != 15 */
+
+
+/* XXX: optimize */
+
+/*
+ * 15 bit color
+ */
+static void glue(vga_draw_line15_, DEPTH)(VGAState *s1, uint8_t *d,
+ const uint8_t *s, int width)
+{
+#if DEPTH == 15 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
+ memcpy(d, s, width * 2);
+#else
+ int w;
+ uint32_t v, r, g, b;
+
+ w = width;
+ do {
+ v = lduw_raw((void *)s);
+ r = (v >> 7) & 0xf8;
+ g = (v >> 2) & 0xf8;
+ b = (v << 3) & 0xf8;
+ ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
+ s += 2;
+ d += BPP;
+ } while (--w != 0);
+#endif
+}
+
+/*
+ * 16 bit color
+ */
+static void glue(vga_draw_line16_, DEPTH)(VGAState *s1, uint8_t *d,
+ const uint8_t *s, int width)
+{
+#if DEPTH == 16 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
+ memcpy(d, s, width * 2);
+#else
+ int w;
+ uint32_t v, r, g, b;
+
+ w = width;
+ do {
+ v = lduw_raw((void *)s);
+ r = (v >> 8) & 0xf8;
+ g = (v >> 3) & 0xfc;
+ b = (v << 3) & 0xf8;
+ ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
+ s += 2;
+ d += BPP;
+ } while (--w != 0);
+#endif
+}
+
+/*
+ * 24 bit color
+ */
+static void glue(vga_draw_line24_, DEPTH)(VGAState *s1, uint8_t *d,
+ const uint8_t *s, int width)
+{
+ int w;
+ uint32_t r, g, b;
+
+ w = width;
+ do {
+#if defined(TARGET_WORDS_BIGENDIAN)
+ r = s[0];
+ g = s[1];
+ b = s[2];
+#else
+ b = s[0];
+ g = s[1];
+ r = s[2];
+#endif
+ ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
+ s += 3;
+ d += BPP;
+ } while (--w != 0);
+}
+
+/*
+ * 32 bit color
+ */
+static void glue(vga_draw_line32_, DEPTH)(VGAState *s1, uint8_t *d,
+ const uint8_t *s, int width)
+{
+#if DEPTH == 32 && defined(WORDS_BIGENDIAN) == defined(TARGET_WORDS_BIGENDIAN)
+ memcpy(d, s, width * 4);
+#else
+ int w;
+ uint32_t r, g, b;
+
+ w = width;
+ do {
+#if defined(TARGET_WORDS_BIGENDIAN)
+ r = s[1];
+ g = s[2];
+ b = s[3];
+#else
+ b = s[0];
+ g = s[1];
+ r = s[2];
+#endif
+ ((PIXEL_TYPE *)d)[0] = glue(rgb_to_pixel, DEPTH)(r, g, b);
+ s += 4;
+ d += BPP;
+ } while (--w != 0);
+#endif
+}
+
+#if DEPTH != 15
+void glue(vga_draw_cursor_line_, DEPTH)(uint8_t *d1,
+ const uint8_t *src1,
+ int poffset, int w,
+ unsigned int color0,
+ unsigned int color1,
+ unsigned int color_xor)
+{
+ const uint8_t *plane0, *plane1;
+ int x, b0, b1;
+ uint8_t *d;
+
+ d = d1;
+ plane0 = src1;
+ plane1 = src1 + poffset;
+ for(x = 0; x < w; x++) {
+ b0 = (plane0[x >> 3] >> (7 - (x & 7))) & 1;
+ b1 = (plane1[x >> 3] >> (7 - (x & 7))) & 1;
+#if DEPTH == 8
+ switch(b0 | (b1 << 1)) {
+ case 0:
+ break;
+ case 1:
+ d[0] ^= color_xor;
+ break;
+ case 2:
+ d[0] = color0;
+ break;
+ case 3:
+ d[0] = color1;
+ break;
+ }
+#elif DEPTH == 16
+ switch(b0 | (b1 << 1)) {
+ case 0:
+ break;
+ case 1:
+ ((uint16_t *)d)[0] ^= color_xor;
+ break;
+ case 2:
+ ((uint16_t *)d)[0] = color0;
+ break;
+ case 3:
+ ((uint16_t *)d)[0] = color1;
+ break;
+ }
+#elif DEPTH == 32
+ switch(b0 | (b1 << 1)) {
+ case 0:
+ break;
+ case 1:
+ ((uint32_t *)d)[0] ^= color_xor;
+ break;
+ case 2:
+ ((uint32_t *)d)[0] = color0;
+ break;
+ case 3:
+ ((uint32_t *)d)[0] = color1;
+ break;
+ }
+#else
+#error unsupported depth
+#endif
+ d += BPP;
+ }
+}
+#endif
+
+#undef PUT_PIXEL2
+#undef DEPTH
+#undef BPP
+#undef PIXEL_TYPE
--- /dev/null
+/* ld script to make i386 Linux kernel
+ * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>;
+ */
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_ARCH(i386)
+SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/alpha-unknown-linux-gnu/lib);
+ENTRY(_start)
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = 0xa8000000 + SIZEOF_HEADERS;
+ .interp : { *(.interp) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .gnu.version : { *(.gnu.version) }
+ .gnu.version_d : { *(.gnu.version_d) }
+ .gnu.version_r : { *(.gnu.version_r) }
+ .rel.text :
+ { *(.rel.text) *(.rel.gnu.linkonce.t*) }
+ .rela.text :
+ { *(.rela.text) *(.rela.gnu.linkonce.t*) }
+ .rel.data :
+ { *(.rel.data) *(.rel.gnu.linkonce.d*) }
+ .rela.data :
+ { *(.rela.data) *(.rela.gnu.linkonce.d*) }
+ .rel.rodata :
+ { *(.rel.rodata) *(.rel.gnu.linkonce.r*) }
+ .rela.rodata :
+ { *(.rela.rodata) *(.rela.gnu.linkonce.r*) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.init : { *(.rel.init) }
+ .rela.init : { *(.rela.init) }
+ .rel.fini : { *(.rel.fini) }
+ .rela.fini : { *(.rela.fini) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init : { *(.init) } =0x47ff041f
+ .text :
+ {
+ *(.text)
+ /* .gnu.warning sections are handled specially by elf32.em. */
+ *(.gnu.warning)
+ *(.gnu.linkonce.t*)
+ } =0x47ff041f
+ _etext = .;
+ PROVIDE (etext = .);
+ .fini : { *(.fini) } =0x47ff041f
+ .rodata : { *(.rodata) *(.gnu.linkonce.r*) }
+ .rodata1 : { *(.rodata1) }
+ .reginfo : { *(.reginfo) }
+ __preinit_array_start = .;
+ .preinit_array : { *(.preinit_array) }
+ __preinit_array_end = .;
+ __init_array_start = .;
+ .init_array : { *(.init_array) }
+ __init_array_end = .;
+ __fini_array_start = .;
+ .fini_array : { *(.fini_array) }
+ __fini_array_end = .;
+
+ /* Adjust the address for the data segment. We want to adjust up to
+ the same address within the page on the next page up. */
+ . = ALIGN(0x100000) + (. & (0x100000 - 1));
+ .data :
+ {
+ *(.data)
+ *(.gnu.linkonce.d*)
+ CONSTRUCTORS
+ }
+ .data1 : { *(.data1) }
+ .ctors :
+ {
+ *(.ctors)
+ }
+ .dtors :
+ {
+ *(.dtors)
+ }
+ .plt : { *(.plt) }
+ .got : { *(.got.plt) *(.got) }
+ .dynamic : { *(.dynamic) }
+ /* We want the small data sections together, so single-instruction offsets
+ can access them all, and initialized data all before uninitialized, so
+ we can shorten the on-disk segment size. */
+ .sdata : { *(.sdata) }
+ _edata = .;
+ PROVIDE (edata = .);
+ __bss_start = .;
+ .sbss : { *(.sbss) *(.scommon) }
+ .bss :
+ {
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ }
+ _end = . ;
+ PROVIDE (end = .);
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+ /* DWARF debug sections.
+ Symbols in the DWARF debugging sections are relative to the beginning
+ of the section so we begin them at 0. */
+ /* DWARF 1 */
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+ /* GNU DWARF 1 extensions */
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ /* DWARF 1.1 and DWARF 2 */
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ /* DWARF 2 */
+ .debug_info 0 : { *(.debug_info) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+ /* SGI/MIPS DWARF 2 extensions */
+ .debug_weaknames 0 : { *(.debug_weaknames) }
+ .debug_funcnames 0 : { *(.debug_funcnames) }
+ .debug_typenames 0 : { *(.debug_typenames) }
+ .debug_varnames 0 : { *(.debug_varnames) }
+ /* These must appear regardless of . */
+}
--- /dev/null
+/* ld script to make i386 Linux kernel
+ * Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>;
+ */
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_ARCH(i386)
+SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/alpha-unknown-linux-gnu/lib);
+ENTRY(_start)
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = 0x60000000 + SIZEOF_HEADERS;
+ .interp : { *(.interp) }
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .gnu.version : { *(.gnu.version) }
+ .gnu.version_d : { *(.gnu.version_d) }
+ .gnu.version_r : { *(.gnu.version_r) }
+ .rel.text :
+ { *(.rel.text) *(.rel.gnu.linkonce.t*) }
+ .rela.text :
+ { *(.rela.text) *(.rela.gnu.linkonce.t*) }
+ .rel.data :
+ { *(.rel.data) *(.rel.gnu.linkonce.d*) }
+ .rela.data :
+ { *(.rela.data) *(.rela.gnu.linkonce.d*) }
+ .rel.rodata :
+ { *(.rel.rodata) *(.rel.gnu.linkonce.r*) }
+ .rela.rodata :
+ { *(.rela.rodata) *(.rela.gnu.linkonce.r*) }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.init : { *(.rel.init) }
+ .rela.init : { *(.rela.init) }
+ .rel.fini : { *(.rel.fini) }
+ .rela.fini : { *(.rela.fini) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .init : { *(.init) } =0x47ff041f
+ .text :
+ {
+ *(.text)
+ /* .gnu.warning sections are handled specially by elf32.em. */
+ *(.gnu.warning)
+ *(.gnu.linkonce.t*)
+ } =0x47ff041f
+ _etext = .;
+ PROVIDE (etext = .);
+ .fini : { *(.fini) } =0x47ff041f
+ . = ALIGN(32 / 8);
+ PROVIDE (__preinit_array_start = .);
+ .preinit_array : { *(.preinit_array) }
+ PROVIDE (__preinit_array_end = .);
+ PROVIDE (__init_array_start = .);
+ .init_array : { *(.init_array) }
+ PROVIDE (__init_array_end = .);
+ PROVIDE (__fini_array_start = .);
+ .fini_array : { *(.fini_array) }
+ PROVIDE (__fini_array_end = .);
+ .rodata : { *(.rodata) *(.gnu.linkonce.r*) }
+ .rodata1 : { *(.rodata1) }
+ .reginfo : { *(.reginfo) }
+ /* Adjust the address for the data segment. We want to adjust up to
+ the same address within the page on the next page up. */
+ . = ALIGN(0x100000) + (. & (0x100000 - 1));
+ .data :
+ {
+ *(.data)
+ *(.gnu.linkonce.d*)
+ CONSTRUCTORS
+ }
+ .data1 : { *(.data1) }
+ .ctors :
+ {
+ *(.ctors)
+ }
+ .dtors :
+ {
+ *(.dtors)
+ }
+ .plt : { *(.plt) }
+ .got : { *(.got.plt) *(.got) }
+ .dynamic : { *(.dynamic) }
+ /* We want the small data sections together, so single-instruction offsets
+ can access them all, and initialized data all before uninitialized, so
+ we can shorten the on-disk segment size. */
+ .sdata : { *(.sdata) }
+ _edata = .;
+ PROVIDE (edata = .);
+ __bss_start = .;
+ .sbss : { *(.sbss) *(.scommon) }
+ .bss :
+ {
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ }
+ _end = . ;
+ PROVIDE (end = .);
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+ /* DWARF debug sections.
+ Symbols in the DWARF debugging sections are relative to the beginning
+ of the section so we begin them at 0. */
+ /* DWARF 1 */
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+ /* GNU DWARF 1 extensions */
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ /* DWARF 1.1 and DWARF 2 */
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ /* DWARF 2 */
+ .debug_info 0 : { *(.debug_info) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+ /* SGI/MIPS DWARF 2 extensions */
+ .debug_weaknames 0 : { *(.debug_weaknames) }
+ .debug_funcnames 0 : { *(.debug_funcnames) }
+ .debug_typenames 0 : { *(.debug_typenames) }
+ .debug_varnames 0 : { *(.debug_varnames) }
+ /* These must appear regardless of . */
+}
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: bochs.h,v 1.128.2.1 2004/02/06 22:14:25 danielg4 Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-//
-// bochs.h is the master header file for all C++ code. It includes all
-// the system header files needed by bochs, and also includes all the bochs
-// C++ header files. Because bochs.h and the files that it includes has
-// structure and class definitions, it cannot be called from C code.
-//
-
-#ifndef BX_BOCHS_H
-# define BX_BOCHS_H 1
-
-#include "config.h" /* generated by configure script from config.h.in */
-
-extern "C" {
-
-#ifdef WIN32
-// In a win32 compile (including cygwin), windows.h is required for several
-// files in gui and iodev. It is important to include it here in a header
-// file so that WIN32-specific data types can be used in fields of classes.
-#include <windows.h>
-#endif
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <assert.h>
-#include <errno.h>
-
-#ifndef WIN32
-# include <unistd.h>
-#else
-# include <io.h>
-#endif
-#include <time.h>
-#if BX_WITH_MACOS
-#define Float32 KLUDGE_Float32
-#define Float64 KLUDGE_Float64
-# include <types.h>
-#undef Float32
-#undef Float64
-# include <stat.h>
-# include <cstdio>
-# include <unistd.h>
-#elif BX_WITH_CARBON
-# include <sys/types.h>
-# include <sys/stat.h>
-# include <sys/param.h> /* for MAXPATHLEN */
-# include <utime.h>
-#else
-# ifndef WIN32
-# include <sys/time.h>
-# endif
-# include <sys/types.h>
-# include <sys/stat.h>
-#endif
-#include <ctype.h>
-#include <string.h>
-#include <fcntl.h>
-#include <limits.h>
-#ifdef macintosh
-# define SuperDrive "[fd:]"
-#endif
-}
-
-#include "osdep.h" /* platform dependent includes and defines */
-#include "bxversion.h"
-
-#include "gui/siminterface.h"
-
-// prototypes
-int bx_begin_simulation (int argc, char *argv[]);
-
-//
-// some macros to interface the CPU and memory to external environment
-// so that these functions can be redirected to the debugger when
-// needed.
-//
-
-#if ((BX_DEBUGGER == 1) && (BX_NUM_SIMULATORS >= 2))
-// =-=-=-=-=-=-=- Redirected to cosimulation debugger -=-=-=-=-=-=-=
-#define DEV_vga_mem_read(addr) bx_dbg_ucmem_read(addr)
-#define DEV_vga_mem_write(addr, val) bx_dbg_ucmem_write(addr, val)
-
-#if BX_SUPPORT_A20
-# define A20ADDR(x) ( (x) & bx_pc_system.a20_mask )
-#else
-# define A20ADDR(x) (x)
-#endif
-#define BX_INP(addr, len) bx_dbg_inp(addr, len)
-#define BX_OUTP(addr, val, len) bx_dbg_outp(addr, val, len)
-#define BX_HRQ (bx_pc_system.HRQ)
-#define BX_RAISE_HLDA() bx_dbg_raise_HLDA()
-#define BX_TICK1()
-#define BX_INTR bx_pc_system.INTR
-#define BX_SET_INTR(b) bx_dbg_set_INTR(b)
-#if BX_SIM_ID == 0
-# define BX_CPU_C bx_cpu0_c
-# define BX_CPU bx_cpu0
-# define BX_MEM_C bx_mem0_c
-# define BX_MEM bx_mem0
-#else
-# define BX_CPU_C bx_cpu1_c
-# define BX_CPU bx_cpu1
-# define BX_MEM_C bx_mem1_c
-# define BX_MEM bx_mem1
-#endif
-#define BX_SET_ENABLE_A20(enabled) bx_dbg_async_pin_request(BX_DBG_ASYNC_PENDING_A20, \
- enabled)
-#define BX_GET_ENABLE_A20() bx_pc_system.get_enable_a20()
-#error FIXME: cosim mode not fixed yet
-
-#else
-
-// =-=-=-=-=-=-=- Normal optimized use -=-=-=-=-=-=-=-=-=-=-=-=-=-=
-#if BX_SUPPORT_A20
-# define A20ADDR(x) ( (x) & bx_pc_system.a20_mask )
-#else
-# define A20ADDR(x) (x)
-#endif
-//
-// some pc_systems functions just redirect to the IO devices so optimize
-// by eliminating call here
-//
-// #define BX_INP(addr, len) bx_pc_system.inp(addr, len)
-// #define BX_OUTP(addr, val, len) bx_pc_system.outp(addr, val, len)
-#define BX_INP(addr, len) bx_devices.inp(addr, len)
-#define BX_OUTP(addr, val, len) bx_devices.outp(addr, val, len)
-#define BX_TICK1() bx_pc_system.tick1()
-#define BX_TICKN(n) bx_pc_system.tickn(n)
-#define BX_INTR bx_pc_system.INTR
-#define BX_SET_INTR(b) bx_pc_system.set_INTR(b)
-#define BX_CPU_C bx_cpu_c
-#define BX_MEM_C bx_mem_c
-#define BX_HRQ (bx_pc_system.HRQ)
-#define BX_MEM_READ_PHYSICAL(phy_addr, len, ptr) \
- BX_MEM(0)->readPhysicalPage(BX_CPU(0), phy_addr, len, ptr)
-#define BX_MEM_WRITE_PHYSICAL(phy_addr, len, ptr) \
- BX_MEM(0)->writePhysicalPage(BX_CPU(0), phy_addr, len, ptr)
-
-#if BX_SMP_PROCESSORS==1
-#define BX_CPU(x) (&bx_cpu)
-#define BX_MEM(x) (&bx_mem)
-#else
-#define BX_CPU(x) (bx_cpu_array[x])
-#define BX_MEM(x) (bx_mem_array[x])
-#endif
-
-#define BX_SET_ENABLE_A20(enabled) bx_pc_system.set_enable_a20(enabled)
-#define BX_GET_ENABLE_A20() bx_pc_system.get_enable_a20()
-
-#endif
-
-
-// you can't use static member functions on the CPU, if there are going
-// to be 2 cpus. Check this early on.
-#if (BX_SMP_PROCESSORS>1)
-# if (BX_USE_CPU_SMF!=0)
-# error For SMP simulation, BX_USE_CPU_SMF must be 0.
-# endif
-#endif
-
-
-// #define BX_IAC() bx_pc_system.IAC()
-//#define BX_IAC() bx_dbg_IAC()
-
-//
-// Ways for the the external environment to report back information
-// to the debugger.
-//
-
-#if BX_DEBUGGER
-# define BX_DBG_ASYNC_INTR bx_guard.async.irq
-# define BX_DBG_ASYNC_DMA bx_guard.async.dma
-#if (BX_NUM_SIMULATORS > 1)
-// for multiple simulators, we always need this info, since we're
-// going to replay it.
-# define BX_DBG_DMA_REPORT(addr, len, what, val) \
- bx_dbg_dma_report(addr, len, what, val)
-# define BX_DBG_IAC_REPORT(vector, irq) \
- bx_dbg_iac_report(vector, irq)
-# define BX_DBG_A20_REPORT(val) \
- bx_dbg_a20_report(val)
-# define BX_DBG_IO_REPORT(addr, size, op, val) \
- bx_dbg_io_report(addr, size, op, val)
-# define BX_DBG_UCMEM_REPORT(addr, size, op, val)
-#else
-// for a single simulator debug environment, we can optimize a little
-// by conditionally calling, as per requested.
-
-# define BX_DBG_DMA_REPORT(addr, len, what, val) \
- if (bx_guard.report.dma) bx_dbg_dma_report(addr, len, what, val)
-# define BX_DBG_IAC_REPORT(vector, irq) \
- if (bx_guard.report.irq) bx_dbg_iac_report(vector, irq)
-# define BX_DBG_A20_REPORT(val) \
- if (bx_guard.report.a20) bx_dbg_a20_report(val)
-# define BX_DBG_IO_REPORT(addr, size, op, val) \
- if (bx_guard.report.io) bx_dbg_io_report(addr, size, op, val)
-# define BX_DBG_UCMEM_REPORT(addr, size, op, val) \
- if (bx_guard.report.ucmem) bx_dbg_ucmem_report(addr, size, op, val)
-#endif // #if (BX_NUM_SIMULATORS > 1)
-
-#else // #if BX_DEBUGGER
-// debugger not compiled in, use empty stubs
-# define BX_DBG_ASYNC_INTR 1
-# define BX_DBG_ASYNC_DMA 1
-# define BX_DBG_DMA_REPORT(addr, len, what, val)
-# define BX_DBG_IAC_REPORT(vector, irq)
-# define BX_DBG_A20_REPORT(val)
-# define BX_DBG_IO_REPORT(addr, size, op, val)
-# define BX_DBG_UCMEM_REPORT(addr, size, op, val)
-#endif // #if BX_DEBUGGER
-
-#define MAGIC_LOGNUM 0x12345678
-
-typedef class BOCHSAPI logfunctions {
- char *prefix;
- int type;
-// values of onoff: 0=ignore, 1=report, 2=ask, 3=fatal
-#define ACT_IGNORE 0
-#define ACT_REPORT 1
-#define ACT_ASK 2
-#define ACT_FATAL 3
-#define N_ACT 4
- int onoff[N_LOGLEV];
- class iofunctions *logio;
- // default log actions for all devices, declared and initialized
- // in logio.cc.
- BOCHSAPI_CYGONLY static int default_onoff[N_LOGLEV];
-public:
- logfunctions(void);
- logfunctions(class iofunctions *);
- ~logfunctions(void);
-
- void info(const char *fmt, ...) BX_CPP_AttrPrintf(2, 3);
- void error(const char *fmt, ...) BX_CPP_AttrPrintf(2, 3);
- void panic(const char *fmt, ...) BX_CPP_AttrPrintf(2, 3);
- void pass(const char *fmt, ...) BX_CPP_AttrPrintf(2, 3);
- void ldebug(const char *fmt, ...) BX_CPP_AttrPrintf(2, 3);
- void fatal (const char *prefix, const char *fmt, va_list ap, int exit_status);
-#if BX_EXTERNAL_DEBUGGER
- virtual void ask (int level, const char *prefix, const char *fmt, va_list ap);
-#else
- void ask (int level, const char *prefix, const char *fmt, va_list ap);
-#endif
- void put(char *);
- void settype(int);
- void setio(class iofunctions *);
- void setonoff(int loglev, int value) {
- assert (loglev >= 0 && loglev < N_LOGLEV);
- onoff[loglev] = value;
- }
- char *getprefix () { return prefix; }
- int getonoff(int level) {
- assert (level>=0 && level<N_LOGLEV);
- return onoff[level];
- }
- static void set_default_action (int loglev, int action) {
- assert (loglev >= 0 && loglev < N_LOGLEV);
- assert (action >= 0 && action < N_ACT);
- default_onoff[loglev] = action;
- }
- static int get_default_action (int loglev) {
- assert (loglev >= 0 && loglev < N_LOGLEV);
- return default_onoff[loglev];
- }
-} logfunc_t;
-
-#define BX_LOGPREFIX_SIZE 51
-
-enum {
- IOLOG=0, FDLOG, GENLOG, CMOSLOG, CDLOG, DMALOG, ETHLOG, G2HLOG, HDLOG, KBDLOG,
- NE2KLOG, PARLOG, PCILOG, PICLOG, PITLOG, SB16LOG, SERLOG, VGALOG,
- STLOG, // state_file.cc
- DEVLOG, MEMLOG, DISLOG, GUILOG, IOAPICLOG, APICLOG, CPU0LOG, CPU1LOG,
- CPU2LOG, CPU3LOG, CPU4LOG, CPU5LOG, CPU6LOG, CPU7LOG, CPU8LOG, CPU9LOG,
- CPU10LOG, CPU11LOG, CPU12LOG, CPU13LOG, CPU14LOG, CPU15LOG, CTRLLOG,
- UNMAPLOG, SERRLOG, BIOSLOG, PIT81LOG, PIT82LOG, IODEBUGLOG, PCI2ISALOG,
- PLUGINLOG, EXTFPUIRQLOG , PCIVGALOG, PCIUSBLOG, VTIMERLOG, STIMERLOG
-};
-
-class BOCHSAPI iofunctions {
- int magic;
- char logprefix[BX_LOGPREFIX_SIZE];
- FILE *logfd;
- class logfunctions *log;
- void init(void);
- void flush(void);
-
-// Log Class types
-public:
- iofunctions(void);
- iofunctions(FILE *);
- iofunctions(int);
- iofunctions(const char *);
- ~iofunctions(void);
-
- void out(int facility, int level, const char *pre, const char *fmt, va_list ap);
-
- void init_log(const char *fn);
- void init_log(int fd);
- void init_log(FILE *fs);
- void set_log_prefix(const char *prefix);
- int get_n_logfns () { return n_logfn; }
- logfunc_t *get_logfn (int index) { return logfn_list[index]; }
- void add_logfn (logfunc_t *fn);
- void set_log_action (int loglevel, int action);
- const char *getlevel(int i) {
- static const char *loglevel[N_LOGLEV] = {
- "DEBUG",
- "INFO",
- "ERROR",
- "PANIC",
- "PASS"
- };
- if (i>=0 && i<N_LOGLEV) return loglevel[i];
- else return "?";
- }
- char *getaction(int i) {
- static char *name[] = { "ignore", "report", "ask", "fatal" };
- assert (i>=ACT_IGNORE && i<N_ACT);
- return name[i];
- }
-
-protected:
- int n_logfn;
-#define MAX_LOGFNS 128
- logfunc_t *logfn_list[MAX_LOGFNS];
- char *logfn;
-
-
-};
-
-typedef class BOCHSAPI iofunctions iofunc_t;
-
-
-#define SAFE_GET_IOFUNC() \
- ((io==NULL)? (io=new iofunc_t("/dev/stderr")) : io)
-#define SAFE_GET_GENLOG() \
- ((genlog==NULL)? (genlog=new logfunc_t(SAFE_GET_IOFUNC())) : genlog)
-/* #define NO_LOGGING */
-#ifndef NO_LOGGING
-
-#define BX_INFO(x) (LOG_THIS info) x
-#define BX_DEBUG(x) (LOG_THIS ldebug) x
-#define BX_ERROR(x) (LOG_THIS error) x
-#define BX_PANIC(x) (LOG_THIS panic) x
-#define BX_PASS(x) (LOG_THIS pass) x
-
-#else
-
-#define EMPTY do { } while(0)
-
-#define BX_INFO(x) EMPTY
-#define BX_DEBUG(x) EMPTY
-#define BX_ERROR(x) EMPTY
-#define BX_PANIC(x) (LOG_THIS panic) x
-#define BX_PASS(x) (LOG_THIS pass) x
-
-#endif
-
-BOCHSAPI extern iofunc_t *io;
-BOCHSAPI extern logfunc_t *genlog;
-
-#include "state_file.h"
-
-#ifndef UNUSED
-# define UNUSED(x) ((void)x)
-#endif
-
-#define uint8 Bit8u
-#define uint16 Bit16u
-#define uint32 Bit32u
-
-#ifdef BX_USE_VMX
-extern "C" {
-#include "xc.h"
-}
-
-extern void *shared_page;
-BOCHSAPI extern int xc_handle;
-#endif
-
-#if BX_PROVIDE_CPU_MEMORY==1
-# include "cpu/cpu.h"
-#endif
-
-#if BX_EXTERNAL_DEBUGGER
-# include "cpu/extdb.h"
-#endif
-
-#if BX_GDBSTUB
-// defines for GDB stub
-void bx_gdbstub_init(int argc, char* argv[]);
-int bx_gdbstub_check(unsigned int eip);
-#define GDBSTUB_STOP_NO_REASON (0xac0)
-
-#if BX_SMP_PROCESSORS!=1
-#error GDB stub was written for single processor support. If multiprocessor support is added, then we can remove this check.
-// The big problem is knowing which CPU gdb is referring to. In other words,
-// what should we put for "n" in BX_CPU(n)->dbg_xlate_linear2phy() and
-// BX_CPU(n)->dword.eip, etc.
-#endif
-
-#endif
-
-#if BX_DISASM
-# include "disasm/disasm.h"
-#endif
-
-typedef struct {
- bx_bool floppy;
- bx_bool keyboard;
- bx_bool video;
- bx_bool disk;
- bx_bool pit;
- bx_bool pic;
- bx_bool bios;
- bx_bool cmos;
- bx_bool a20;
- bx_bool interrupts;
- bx_bool exceptions;
- bx_bool unsupported;
- bx_bool temp;
- bx_bool reset;
- bx_bool debugger;
- bx_bool mouse;
- bx_bool io;
- bx_bool xms;
- bx_bool v8086;
- bx_bool paging;
- bx_bool creg;
- bx_bool dreg;
- bx_bool dma;
- bx_bool unsupported_io;
- bx_bool serial;
- bx_bool cdrom;
-#ifdef MAGIC_BREAKPOINT
- bx_bool magic_break_enabled;
-#endif /* MAGIC_BREAKPOINT */
-#if BX_SUPPORT_APIC
- bx_bool apic;
- bx_bool ioapic;
-#endif
-#if BX_DEBUG_LINUX
- bx_bool linux_syscall;
-#endif
- void* record_io;
- } bx_debug_t;
-
-#define BX_ASSERT(x) do {if (!(x)) BX_PANIC(("failed assertion \"%s\" at %s:%d\n", #x, __FILE__, __LINE__));} while (0)
-void bx_signal_handler (int signum);
-int bx_atexit(void);
-BOCHSAPI extern bx_debug_t bx_dbg;
-
-
-
-/* Already in gui/siminterface.h ???
-#define BX_FLOPPY_NONE 10 // floppy not present
-#define BX_FLOPPY_1_2 11 // 1.2M 5.25"
-#define BX_FLOPPY_1_44 12 // 1.44M 3.5"
-#define BX_FLOPPY_2_88 13 // 2.88M 3.5"
-#define BX_FLOPPY_720K 14 // 720K 3.5"
-#define BX_FLOPPY_360K 15 // 360K 5.25"
-#define BX_FLOPPY_LAST 15 // last one
-*/
-
-
-#define BX_READ 0
-#define BX_WRITE 1
-#define BX_RW 2
-
-
-
-
-
-#include "memory/memory.h"
-
-
-enum PCS_OP { PCS_CLEAR, PCS_SET, PCS_TOGGLE };
-
-#include "pc_system.h"
-#include "plugin.h"
-#include "gui/gui.h"
-#include "gui/textconfig.h"
-#include "gui/keymap.h"
-#include "iodev/iodev.h"
-
-
-
-
-
-
-
-/* --- EXTERNS --- */
-
-#if ( BX_PROVIDE_DEVICE_MODELS==1 )
-BOCHSAPI extern bx_devices_c bx_devices;
-#endif
-
-#if BX_GUI_SIGHANDLER
-extern bx_bool bx_gui_sighandler;
-#endif
-
-// This value controls how often each I/O device's periodic() method
-// gets called. The timer is set up in iodev/devices.cc.
-#define BX_IODEV_HANDLER_PERIOD 100 // microseconds
-//#define BX_IODEV_HANDLER_PERIOD 10 // microseconds
-
-char *bx_find_bochsrc (void);
-int bx_parse_cmdline (int arg, int argc, char *argv[]);
-int bx_read_configuration (char *rcfile);
-int bx_write_configuration (char *rcfile, int overwrite);
-void bx_reset_options (void);
-
-#define BX_PATHNAME_LEN 512
-
-typedef struct {
- bx_param_bool_c *Opresent;
- bx_param_num_c *Oioaddr1;
- bx_param_num_c *Oioaddr2;
- bx_param_num_c *Oirq;
- } bx_ata_options;
-
-typedef struct {
- bx_param_string_c *Opath;
- bx_param_num_c *Oaddress;
- } bx_rom_options;
-
-typedef struct {
- bx_param_string_c *Opath;
- } bx_vgarom_options;
-
-typedef struct {
- bx_param_num_c *Osize;
- } bx_mem_options;
-
-typedef struct {
- bx_param_bool_c *Oenabled;
- bx_param_string_c *Ooutfile;
-} bx_parport_options;
-
-typedef struct {
- bx_param_string_c *Opath;
- bx_param_bool_c *OcmosImage;
- } bx_cmos_options;
-
-typedef struct {
- bx_param_num_c *Otime0;
- bx_param_enum_c *Osync;
- } bx_clock_options;
-
-typedef struct {
- bx_param_bool_c *Opresent;
- bx_param_num_c *Oioaddr;
- bx_param_num_c *Oirq;
- bx_param_string_c *Omacaddr;
- bx_param_enum_c *Oethmod;
- bx_param_string_c *Oethdev;
- bx_param_string_c *Oscript;
- } bx_ne2k_options;
-
-typedef struct {
-// These options are used for a special hack to load a
-// 32bit OS directly into memory, so it can be run without
-// any of the 16bit real mode or BIOS assistance. This
-// is for the development of plex86, so we don't have
-// to implement real mode up front.
- bx_param_num_c *OwhichOS;
- bx_param_string_c *Opath;
- bx_param_string_c *Oiolog;
- bx_param_string_c *Oinitrd;
- } bx_load32bitOSImage_t;
-
-typedef struct {
- bx_param_string_c *Ofilename;
- bx_param_string_c *Oprefix;
- bx_param_string_c *Odebugger_filename;
-} bx_log_options;
-
-typedef struct {
- bx_param_bool_c *Opresent;
- bx_param_string_c *Omidifile;
- bx_param_string_c *Owavefile;
- bx_param_string_c *Ologfile;
- bx_param_num_c *Omidimode;
- bx_param_num_c *Owavemode;
- bx_param_num_c *Ologlevel;
- bx_param_num_c *Odmatimer;
- } bx_sb16_options;
-
-typedef struct {
- unsigned int port;
- unsigned int text_base;
- unsigned int data_base;
- unsigned int bss_base;
- } bx_gdbstub_t;
-
-typedef struct {
- bx_param_bool_c *OuseMapping;
- bx_param_string_c *Okeymap;
- } bx_keyboard_options;
-
-#define BX_KBD_XT_TYPE 0
-#define BX_KBD_AT_TYPE 1
-#define BX_KBD_MF_TYPE 2
-
-#define BX_N_OPTROM_IMAGES 4
-#define BX_N_SERIAL_PORTS 1
-#define BX_N_PARALLEL_PORTS 1
-#define BX_N_USB_HUBS 1
-
-typedef struct BOCHSAPI {
- bx_floppy_options floppya;
- bx_floppy_options floppyb;
- bx_ata_options ata[BX_MAX_ATA_CHANNEL];
- bx_atadevice_options atadevice[BX_MAX_ATA_CHANNEL][2];
- // bx_disk_options diskc;
- // bx_disk_options diskd;
- // bx_cdrom_options cdromd;
- bx_serial_options com[BX_N_SERIAL_PORTS];
- bx_usb_options usb[BX_N_USB_HUBS];
- bx_rom_options rom;
- bx_vgarom_options vgarom;
- bx_rom_options optrom[BX_N_OPTROM_IMAGES]; // Optional rom images
- bx_mem_options memory;
- bx_parport_options par[BX_N_PARALLEL_PORTS]; // parallel ports
- bx_sb16_options sb16;
- bx_param_num_c *Obootdrive;
- bx_param_bool_c *OfloppySigCheck;
- bx_param_num_c *Ovga_update_interval;
- bx_param_num_c *Okeyboard_serial_delay;
- bx_param_num_c *Okeyboard_paste_delay;
- bx_param_enum_c *Okeyboard_type;
- bx_param_num_c *Ofloppy_command_delay;
- bx_param_num_c *Oips;
- bx_param_bool_c *Orealtime_pit;
- bx_param_bool_c *Otext_snapshot_check;
- bx_param_bool_c *Omouse_enabled;
- bx_param_bool_c *Oprivate_colormap;
-#if BX_WITH_AMIGAOS
- bx_param_bool_c *Ofullscreen;
- bx_param_string_c *Oscreenmode;
-#endif
- bx_param_bool_c *Oi440FXSupport;
- bx_cmos_options cmos;
- bx_clock_options clock;
- bx_ne2k_options ne2k;
- bx_param_bool_c *OnewHardDriveSupport;
- bx_load32bitOSImage_t load32bitOSImage;
- bx_log_options log;
- bx_keyboard_options keyboard;
- bx_param_string_c *Ouser_shortcut;
- bx_gdbstub_t gdbstub;
- bx_param_enum_c *Osel_config;
- bx_param_enum_c *Osel_displaylib;
- } bx_options_t;
-
-BOCHSAPI extern bx_options_t bx_options;
-
-void bx_center_print (FILE *file, char *line, int maxwidth);
-
-#if BX_PROVIDE_CPU_MEMORY==1
-#else
-// # include "external_interface.h"
-#endif
-
-#define BX_USE_PS2_MOUSE 1
-
-int bx_init_hardware ();
-
-#include "instrument.h"
-
-// These are some convenience macros which abstract out accesses between
-// a variable in native byte ordering to/from guest (x86) memory, which is
-// always in little endian format. You must deal with alignment (if your
-// system cares) and endian rearranging. Don't assume anything. You could
-// put some platform specific asm() statements here, to make use of native
-// instructions to help perform these operations more efficiently than C++.
-
-
-#ifdef __i386__
-
-#define WriteHostWordToLittleEndian(hostPtr, nativeVar16) \
- *((Bit16u*)(hostPtr)) = (nativeVar16)
-#define WriteHostDWordToLittleEndian(hostPtr, nativeVar32) \
- *((Bit32u*)(hostPtr)) = (nativeVar32)
-#define WriteHostQWordToLittleEndian(hostPtr, nativeVar64) \
- *((Bit64u*)(hostPtr)) = (nativeVar64)
-#define ReadHostWordFromLittleEndian(hostPtr, nativeVar16) \
- (nativeVar16) = *((Bit16u*)(hostPtr))
-#define ReadHostDWordFromLittleEndian(hostPtr, nativeVar32) \
- (nativeVar32) = *((Bit32u*)(hostPtr))
-#define ReadHostQWordFromLittleEndian(hostPtr, nativeVar64) \
- (nativeVar64) = *((Bit64u*)(hostPtr))
-
-#else
-
-#define WriteHostWordToLittleEndian(hostPtr, nativeVar16) { \
- ((Bit8u *)(hostPtr))[0] = (Bit8u) (nativeVar16); \
- ((Bit8u *)(hostPtr))[1] = (Bit8u) ((nativeVar16)>>8); \
- }
-#define WriteHostDWordToLittleEndian(hostPtr, nativeVar32) { \
- ((Bit8u *)(hostPtr))[0] = (Bit8u) (nativeVar32); \
- ((Bit8u *)(hostPtr))[1] = (Bit8u) ((nativeVar32)>>8); \
- ((Bit8u *)(hostPtr))[2] = (Bit8u) ((nativeVar32)>>16); \
- ((Bit8u *)(hostPtr))[3] = (Bit8u) ((nativeVar32)>>24); \
- }
-#define WriteHostQWordToLittleEndian(hostPtr, nativeVar64) { \
- ((Bit8u *)(hostPtr))[0] = (Bit8u) (nativeVar64); \
- ((Bit8u *)(hostPtr))[1] = (Bit8u) ((nativeVar64)>>8); \
- ((Bit8u *)(hostPtr))[2] = (Bit8u) ((nativeVar64)>>16); \
- ((Bit8u *)(hostPtr))[3] = (Bit8u) ((nativeVar64)>>24); \
- ((Bit8u *)(hostPtr))[4] = (Bit8u) ((nativeVar64)>>32); \
- ((Bit8u *)(hostPtr))[5] = (Bit8u) ((nativeVar64)>>40); \
- ((Bit8u *)(hostPtr))[6] = (Bit8u) ((nativeVar64)>>48); \
- ((Bit8u *)(hostPtr))[7] = (Bit8u) ((nativeVar64)>>56); \
- }
-#define ReadHostWordFromLittleEndian(hostPtr, nativeVar16) { \
- (nativeVar16) = ((Bit16u) ((Bit8u *)(hostPtr))[0]) | \
- (((Bit16u) ((Bit8u *)(hostPtr))[1])<<8) ; \
- }
-#define ReadHostDWordFromLittleEndian(hostPtr, nativeVar32) { \
- (nativeVar32) = ((Bit32u) ((Bit8u *)(hostPtr))[0]) | \
- (((Bit32u) ((Bit8u *)(hostPtr))[1])<<8) | \
- (((Bit32u) ((Bit8u *)(hostPtr))[2])<<16) | \
- (((Bit32u) ((Bit8u *)(hostPtr))[3])<<24); \
- }
-#define ReadHostQWordFromLittleEndian(hostPtr, nativeVar64) { \
- (nativeVar64) = ((Bit64u) ((Bit8u *)(hostPtr))[0]) | \
- (((Bit64u) ((Bit8u *)(hostPtr))[1])<<8) | \
- (((Bit64u) ((Bit8u *)(hostPtr))[2])<<16) | \
- (((Bit64u) ((Bit8u *)(hostPtr))[3])<<24) | \
- (((Bit64u) ((Bit8u *)(hostPtr))[4])<<32) | \
- (((Bit64u) ((Bit8u *)(hostPtr))[5])<<40) | \
- (((Bit64u) ((Bit8u *)(hostPtr))[6])<<48) | \
- (((Bit64u) ((Bit8u *)(hostPtr))[7])<<56); \
- }
-
-#endif
-
-#ifdef BX_USE_VMX
-extern int domid;
-extern unsigned long megabytes;
-#endif
-
-#endif /* BX_BOCHS_H */
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// This file is checked in as bxversion.h.in. The configure script
-// substitutes variables and creates bxversion.h.
-/////////////////////////////////////////////////////////////////////////
-
-#define VER_STRING "2.1.1"
-#define REL_STRING "February 08, 2004"
+++ /dev/null
-/* config.h. Generated by configure. */
-// Copyright (C) 2001 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-//
-// config.h.in is distributed in the source TAR file. When you run
-// the configure script, it generates config.h with some changes
-// according to your build environment. For example, in config.h.in,
-// SIZEOF_UNSIGNED_CHAR is set to 0. When configure produces config.h
-// it will change "0" to the detected value for your system.
-//
-// config.h contains ONLY preprocessor #defines and a few typedefs.
-// It must be included by both C and C++ files, so it must not
-// contain anything language dependent such as a class declaration.
-//
-
-#ifdef _BX_CONFIG_H_
-#else
-#define _BX_CONFIG_H_ 1
-
-///////////////////////////////////////////////////////////////////
-// USER CONFIGURABLE OPTIONS : EDIT ONLY OPTIONS IN THIS SECTION //
-///////////////////////////////////////////////////////////////////
-
-
-#if 1
-// quit_sim is defined in gui/siminterface.h
-#define BX_EXIT(x) SIM->quit_sim (x)
-#else
-// provide the real main and the usual exit.
-#define BX_EXIT(x) ::exit(x)
-#endif
-
-#define BX_USE_CONFIG_INTERFACE 0
-#define BX_USE_VMX 1
-
-// I have tested the following combinations:
-// * processors=1, bootstrap=0, ioapic_id=1 (uniprocessor system)
-// * processors=2, bootstrap=0, ioapic_id=2
-// * processors=4, bootstrap=2, ioapic_id=4
-#define BX_SMP_PROCESSORS 1
-#define BX_BOOTSTRAP_PROCESSOR 0
-// choose IOAPIC id to be equal to the number of processors. This leaves
-// one space for each processor to have an ID, starting with 0.
-#define BX_IOAPIC_DEFAULT_ID 1
-
-#define BX_ADDRESS_SPACES 1
-// controls how many instances of BX_MEM_C are created. For
-// SMP, use several processors with one shared memory space.
-// For cosimulation, you could use two processors and two address
-// spaces.
-
-#define BX_SUPPORT_APIC 0
-// include in APIC models, required for a multiprocessor system.
-
-#if (BX_SMP_PROCESSORS>1 && !BX_SUPPORT_APIC)
-#error For multiprocessor simulation, BX_SUPPORT_APIC is required.
-#endif
-
-#define BX_DEBUG_LINUX 0
-// if simulating Linux, this provides a few more debugging options
-// such as tracing all system calls.
-
-#define HAVE_LIBREADLINE 0
-#define HAVE_READLINE_HISTORY_H 1
-// adds support for the GNU readline library in the debugger command
-// prompt.
-
-#define HAVE_LOCALE_H 0
-// Define to 1 if you have <locale.h>
-
-// I rebuilt the code which provides timers to IO devices.
-// Setting this to 1 will introduce a little code which
-// will panic out if cases which shouldn't happen occur.
-// Set this to 0 for optimal performance.
-#define BX_TIMER_DEBUG 1
-
-// Settable A20 line. For efficiency, you can disable
-// having a settable A20 line, eliminating conditional
-// code for every physical memory access. You'll have
-// to tell your software not to mess with the A20 line,
-// and accept it as always being on if you change this.
-// 1 = use settable A20 line. (normal)
-// 0 = A20 is like the rest of the address lines
-
-#define BX_SUPPORT_A20 1
-
-// Processor Instructions Per Second
-// To find out what value to use for the 'ips' directive
-// in your '.bochsrc' file, set BX_SHOW_IPS to 1, and
-// run the software in bochs you plan to use most. Bochs
-// will print out periodic IPS ratings. This will change
-// based on the processor mode at the time, and various
-// other factors. You'll get a reasonable estimate though.
-// When you're done, reset BX_SHOW_IPS to 0, do a
-// 'make all-clean', then 'make' again.
-
-#define BX_SHOW_IPS 0
-
-
-#if (BX_SHOW_IPS) && defined(__MINGW32__)
-#define SIGALRM 14
-#endif
-
-// Paging Options:
-// ---------------
-// Support Paging mechanism.
-// 0 = don't support paging at all (DOS & Minix don't require it)
-// 1 = support paging. (Most other OS's require paging)
-// Use Translation Lookaside Buffer (TLB) for caching
-// paging translations. This will make paging mode
-// more efficient. If you're OS doesn't use paging,
-// then you won't need either.
-// 1 = Use a TLB for effiency
-// 0 = don't use a TLB, walk the page tables for every access
-// BX_TLB_SIZE: Number of entries in TLB
-// BX_TLB_INDEX_OF(lpf): This macro is passed the linear page frame
-// (top 20 bits of the linear address. It must map these bits to
-// one of the TLB cache slots, given the size of BX_TLB_SIZE.
-// There will be a many-to-one mapping to each TLB cache slot.
-// When there are collisions, the old entry is overwritten with
-// one for the newest access.
-
-#define BX_SUPPORT_PAGING 1
-#define BX_USE_TLB 1
-
-#define BX_TLB_SIZE 1024
-#define BX_TLB_INDEX_OF(lpf) (((lpf) & 0x003ff000) >> 12)
-
-#define BX_USE_QUICK_TLB_INVALIDATE 0
-
-// Compile in support for DMA & FLOPPY IO. You'll need this
-// if you plan to use the floppy drive emulation. But if
-// you're environment doesn't require it, you can change
-// it to 0.
-
-#define BX_DMA_FLOPPY_IO 1
-
-
-// Default number of Megs of memory to emulate. The
-// 'megs:' directive in the '.bochsrc' file overrides this,
-// allowing per-run settings.
-
-#define BX_DEFAULT_MEM_MEGS 4
-
-
-// CPU level emulation. Default level is set in
-// the configure script. BX_CPU_LEVEL defines the CPU level
-// to emulate. BX_CPU_LEVEL_HACKED is a hack to define the
-// level of some integer instructions, so they can be tested
-// before the rest of the emulation is up to that level.
-
-#define BX_CPU_LEVEL 5
-#define BX_CPU_LEVEL_HACKED 5
-
-// emulate x86-64 instruction set?
-#define BX_SUPPORT_X86_64 0
-
-// Virtual 8086 mode emulation.
-// 1 = compile in support for v8086 mode.
-// 0 = don't compile in support for v8086 mode.
-#define BX_SUPPORT_V8086_MODE 1
-
-// Defines if the simulation should reset on triple fault
-// if set to 0, the simulation will panic.
-#define BX_RESET_ON_TRIPLE_FAULT 1
-
-// Support shadowing of ROM from C0000 to FFFFF.
-// This allows that region to be written to.
-#define BX_SHADOW_RAM 0
-
-// Number of CMOS registers
-#define BX_NUM_CMOS_REGS 64
-//#define BX_NUM_CMOS_REGS 128
-
-// Use Greg Alexander's new PIT model (summer 2001) instead of the original.
-#define BX_USE_NEW_PIT 1
-
-#define BX_USE_SLOWDOWN_TIMER 0
-#define BX_HAVE_SLEEP 1
-#define BX_HAVE_MSLEEP 0
-#define BX_HAVE_USLEEP 1
-#define BX_HAVE_NANOSLEEP 1
-#define BX_HAVE_ABORT 1
-#define BX_HAVE_SOCKLEN_T 1
-#define BX_HAVE_SOCKADDR_IN_SIN_LEN 0
-#define BX_HAVE_GETTIMEOFDAY 1
-#if defined(WIN32)
-#define BX_HAVE_REALTIME_USEC 1
-#else
-#define BX_HAVE_REALTIME_USEC (BX_HAVE_GETTIMEOFDAY)
-#endif
-#define BX_HAVE_MKSTEMP 1
-#define BX_HAVE_SYS_MMAN_H 1
-#define BX_HAVE_XPM_H 1
-#define BX_HAVE_TIMELOCAL 1
-#define BX_HAVE_GMTIME 1
-#define BX_HAVE_MKTIME 1
-
-// This turns on Roland Mainz's idle hack. Presently it is specific to the X11
-// gui. If people try to enable it elsewhere, give a compile error after the
-// gui definition so that they don't waste their time trying.
-#define BX_USE_IDLE_HACK 0
-
-// Minimum Emulated IPS.
-// This is used in the realtime PIT as well as for checking the
-// IPS value set in the config file.
-#define BX_MIN_IPS 200000
-
-// Use Static Member Funtions to eliminate 'this' pointer passing
-// If you want the efficiency of 'C', you can make all the
-// members of the C++ CPU class to be static.
-// This defaults to 1 since it should improve performance, but when
-// SMP mode is enabled, it will be turned off by configure.
-
-#define BX_USE_CPU_SMF 1
-
-// Use static member functions in IO DEVice emulation modules.
-// For efficiency, use C like functions for IO handling,
-// and declare a device instance at compile time,
-// instead of using 'new' and storing the pointer. This
-// eliminates some overhead, especially for high-use IO
-// devices like the disk drive.
-// 1 = Use static member efficiency (normal)
-// 0 = Use nonstatic member functions (use only if you need
-// multiple instances of a device class
-
-#define BX_USE_HD_SMF 1 // Hard drive
-#define BX_USE_BIOS_SMF 1 // BIOS
-#define BX_USE_CMOS_SMF 1 // CMOS
-#define BX_USE_DMA_SMF 1 // DMA
-#define BX_USE_FD_SMF 1 // Floppy
-#define BX_USE_KEY_SMF 1 // Keyboard
-#define BX_USE_PAR_SMF 1 // Parallel
-#define BX_USE_PIC_SMF 1 // PIC
-#define BX_USE_PIT_SMF 1 // PIT
-#define BX_USE_SER_SMF 1 // Serial
-#define BX_USE_UM_SMF 1 // Unmapped
-#define BX_USE_VGA_SMF 1 // VGA
-#define BX_USE_SB16_SMF 1 // Sound (SB 16)
-#define BX_USE_DEV_SMF 1 // System Devices (port92)
-#define BX_USE_PCI_SMF 1 // PCI
-#define BX_USE_P2I_SMF 1 // PCI-to-ISA bridge
-#define BX_USE_PCIVGA_SMF 1 // PCI-VGA
-#define BX_USE_PCIUSB_SMF 1 // USB hub
-#define BX_USE_NE2K_SMF 1 // NE2K
-#define BX_USE_EFI_SMF 1 // External FPU IRQ
-#define BX_USE_GAME_SMF 1 // Gameport
-
-#define BX_PLUGINS 0
-#define BX_HAVE_DLFCN_H 1
-
-#if BX_PLUGINS && \
- ( !BX_USE_HD_SMF || !BX_USE_BIOS_SMF || !BX_USE_CMOS_SMF \
- || !BX_USE_DMA_SMF || !BX_USE_FD_SMF || !BX_USE_KEY_SMF \
- || !BX_USE_PAR_SMF || !BX_USE_PIC_SMF || !BX_USE_PIT_SMF \
- || !BX_USE_SER_SMF || !BX_USE_UM_SMF || !BX_USE_VGA_SMF \
- || !BX_USE_SB16_SMF || !BX_USE_DEV_SMF || !BX_USE_PCI_SMF \
- || !BX_USE_P2I_SMF || !BX_USE_PCIVGA_SMF || !BX_USE_PCIUSB_SMF \
- || !BX_USE_NE2K_SMF || !BX_USE_EFI_SMF || !BX_USE_GAME_SMF)
-#error You must use SMF to have plugins
-#endif
-
-#define BX_SUPPORT_SB16 0
-#define BX_SUPPORT_GAME 0
-
-#if BX_SUPPORT_SB16
-// Use virtual methods for the sound output functions
-#define BX_USE_SOUND_VIRTUAL 1
-// Determines which sound output class is to be used.
-// Currently the following are available:
-// bx_sound_linux_c Output for Linux, to /dev/dsp and /dev/midi00
-// bx_sound_windows_c Output for Windows midi and wave mappers
-// bx_sound_output_c Dummy functions, no output
-#define BX_SOUND_OUTPUT_C bx_sound_output_c
-#endif
-
-#define USE_RAW_SERIAL 0
-
-#define BX_USE_SPECIFIED_TIME0 0
-
-// This enables writing to port 0xe9 and the output
-// is sent to the console. Reading from port 0xe9
-// will return 0xe9 to let you know this is available.
-// Leave this 0 unless you have a reason to use it.
-#define BX_PORT_E9_HACK 1
-
-#define BX_GDBSTUB 0
-
-// This option enables compressed (zlib) hd support
-#define BX_COMPRESSED_HD_SUPPORT 0
-#define BX_HAVE_ZLIB 1
-
-#if BX_COMPRESSED_HD_SUPPORT && !BX_HAVE_ZLIB
-#error You must have zlib to enable compressed hd support
-#endif
-
-// This option defines the number of supported ATA channels.
-// There are up to two drives per ATA channel.
-#define BX_MAX_ATA_CHANNEL 4
-
-#if (BX_MAX_ATA_CHANNEL>4 || BX_MAX_ATA_CHANNEL<1)
-# error "BX_MAX_ATA_CHANNEL should be between 1 and 4"
-#endif
-
-// =================================================================
-// BEGIN: OPTIONAL DEBUGGER SECTION
-//
-// These options are only used if you compile in support for the
-// native command line debugging environment. Typically, the debugger
-// is not used, and this section can be ignored.
-// =================================================================
-
-#define BX_MAX_DIRTY_PAGE_TABLE_MEGS 1024
-
-// Compile in support for virtual/linear/physical breakpoints.
-// Set to 1, only those you need. Recommend using only linear
-// breakpoints, unless you need others. Less supported means
-// slightly faster execution time.
-#define BX_DBG_SUPPORT_VIR_BPOINT 1
-#define BX_DBG_SUPPORT_LIN_BPOINT 1
-#define BX_DBG_SUPPORT_PHY_BPOINT 1
-
-// You need only define one initial breakpoint into each
-// cpu simulator (emulator) here. Each simulator sets callbacks
-// and variables which the debugger uses from then on.
-#define BX_SIM1_INIT bx_dbg_init_cpu_mem_env0
-#ifndef BX_SIM2_INIT
-#define BX_SIM2_INIT bx_dbg_init_cpu_mem_env1
-#endif
-//#define BX_SIM2_INIT sim2_init
-
-// max number of virtual/linear/physical breakpoints handled
-#define BX_DBG_MAX_VIR_BPOINTS 10
-#define BX_DBG_MAX_LIN_BPOINTS 10
-#define BX_DBG_MAX_PHY_BPOINTS 10
-
-// max file pathname size for debugger commands
-#define BX_MAX_PATH 256
-// max nesting level for debug scripts including other scripts
-#define BX_INFILE_DEPTH 10
-// use this command to include (nest) debug scripts
-#define BX_INCLUDE_CMD "source"
-
-// Use either 32 or 64 bit instruction counter for
-// debugger purposes. Uncomment one of these.
-//#define BX_DBG_ICOUNT_SIZE 32
-#define BX_DBG_ICOUNT_SIZE 64
-
-// Make a call to command line debugger extensions. If set to 1,
-// a call is made. An external routine has a chance to process
-// the command. If it does, than the debugger ignores the command.
-#define BX_DBG_EXTENSIONS 0
-
-// =================================================================
-// END: OPTIONAL DEBUGGER SECTION
-// =================================================================
-
-
-//////////////////////////////////////////////////////////////////////
-// END OF USER CONFIGURABLE OPTIONS : DON'T EDIT ANYTHING BELOW !!! //
-// THIS IS GENERATED BY THE ./configure SCRIPT //
-//////////////////////////////////////////////////////////////////////
-
-
-#define BX_WITH_X11 1
-#define BX_WITH_BEOS 0
-#define BX_WITH_WIN32 0
-#define BX_WITH_MACOS 0
-#define BX_WITH_CARBON 0
-#define BX_WITH_NOGUI 0
-#define BX_WITH_TERM 1
-#define BX_WITH_RFB 1
-#define BX_WITH_AMIGAOS 0
-#define BX_WITH_SDL 0
-#define BX_WITH_SVGA 0
-#define BX_WITH_WX 0
-
-// add special export symbols for win32 DLL building. The main code must
-// have __declspec(dllexport) on variables, functions, or classes that the
-// plugins can access. The plugins should #define PLUGGABLE which will
-// activate the __declspec(dllimport) instead.
-#if defined(WIN32) || defined(__CYGWIN__)
-# if BX_PLUGINS && defined(BX_PLUGGABLE)
-// #warning I will import DLL symbols from Bochs main program.
-# define BOCHSAPI __declspec(dllimport)
-# else
-// #warning I will export DLL symbols.
-# define BOCHSAPI __declspec(dllexport)
-# endif
-#endif
-#ifndef BOCHSAPI
-# define BOCHSAPI
-#endif
-
-#if defined(__CYGWIN__)
-// Make BOCHSAPI_CYGONLY exactly the same as BOCHSAPI. This symbol
-// will be used for any cases where Cygwin requires a special tag
-// but VC++ does not.
-#define BOCHSAPI_CYGONLY BOCHSAPI
-#else
-// define the symbol to be empty
-#define BOCHSAPI_CYGONLY /*empty*/
-#endif
-
-#define BX_DEFAULT_CONFIG_INTERFACE "defined_by_configure"
-#define BX_DEFAULT_DISPLAY_LIBRARY "defined_by_configure"
-
-// Roland Mainz's idle hack is presently specific to X11. If people try to
-// enable it elsewhere, give a compile error so that they don't waste their
-// time trying.
-#if (BX_USE_IDLE_HACK && !BX_WITH_X11)
-# error IDLE_HACK will only work with the X11 gui. Correct configure args and retry.
-#endif
-
-#define WORDS_BIGENDIAN 0
-
-#define SIZEOF_UNSIGNED_CHAR 1
-#define SIZEOF_UNSIGNED_SHORT 2
-#define SIZEOF_UNSIGNED_INT 4
-#define SIZEOF_UNSIGNED_LONG 4
-#define SIZEOF_UNSIGNED_LONG_LONG 8
-#define SIZEOF_INT_P 4
-
-#define BX_64BIT_CONSTANTS_USE_LL 1
-#if BX_64BIT_CONSTANTS_USE_LL
-// doesn't work on Microsoft Visual C++, maybe others
-#define BX_CONST64(x) (x##LL)
-#else
-#define BX_CONST64(x) (x)
-#endif
-
-#if defined(WIN32)
- typedef unsigned char Bit8u;
- typedef signed char Bit8s;
- typedef unsigned short Bit16u;
- typedef signed short Bit16s;
- typedef unsigned int Bit32u;
- typedef signed int Bit32s;
-#ifdef __MINGW32__
- typedef unsigned long long Bit64u;
- typedef signed long long Bit64s;
-#include <sys/types.h>
-#else
- typedef unsigned __int64 Bit64u;
- typedef signed __int64 Bit64s;
-#endif
-#elif BX_WITH_MACOS
- typedef unsigned char Bit8u;
- typedef signed char Bit8s;
- typedef unsigned short Bit16u;
- typedef signed short Bit16s;
- typedef unsigned int Bit32u;
- typedef signed int Bit32s;
- typedef unsigned long long Bit64u;
- typedef signed long long Bit64s;
-#else
-
-// Unix like platforms
-
-#if SIZEOF_UNSIGNED_CHAR != 1
-# error "sizeof (unsigned char) != 1"
-#else
- typedef unsigned char Bit8u;
- typedef signed char Bit8s;
-#endif
-
-#if SIZEOF_UNSIGNED_SHORT != 2
-# error "sizeof (unsigned short) != 2"
-#else
- typedef unsigned short Bit16u;
- typedef signed short Bit16s;
-#endif
-
-#if SIZEOF_UNSIGNED_INT == 4
- typedef unsigned int Bit32u;
- typedef signed int Bit32s;
-#elif SIZEOF_UNSIGNED_LONG == 4
- typedef unsigned long Bit32u;
- typedef signed long Bit32s;
-#else
-# error "can't find sizeof(type) of 4 bytes!"
-#endif
-
-#if SIZEOF_UNSIGNED_LONG == 8
- typedef unsigned long Bit64u;
- typedef signed long Bit64s;
-#elif SIZEOF_UNSIGNED_LONG_LONG == 8
- typedef unsigned long long Bit64u;
- typedef signed long long Bit64s;
-#else
-# error "can't find data type of 8 bytes"
-#endif
-
-#endif
-
-// now that Bit32u and Bit64u exist, defined bx_address
-#if BX_SUPPORT_X86_64
-typedef Bit64u bx_address;
-#else
-typedef Bit32u bx_address;
-#endif
-
-
-// technically, in an 8 bit signed the real minimum is -128, not -127.
-// But if you decide to negate -128 you tend to get -128 again, so it's
-// better not to use the absolute maximum in the signed range.
-#define BX_MAX_BIT64U ( (Bit64u) -1 )
-#define BX_MIN_BIT64U ( 0 )
-#define BX_MAX_BIT64S ( ((Bit64u) -1) >> 1 )
-#define BX_MIN_BIT64S ( -(((Bit64u) -1) >> 1) )
-#define BX_MAX_BIT32U ( (Bit32u) -1 )
-#define BX_MIN_BIT32U ( 0 )
-#define BX_MAX_BIT32S ( ((Bit32u) -1) >> 1 )
-#define BX_MIN_BIT32S ( -(((Bit32u) -1) >> 1) )
-#define BX_MAX_BIT16U ( (Bit16u) -1 )
-#define BX_MIN_BIT16U ( 0 )
-#define BX_MAX_BIT16S ( ((Bit16u) -1) >> 1 )
-#define BX_MIN_BIT16S ( -(((Bit16u) -1) >> 1) )
-#define BX_MAX_BIT8U ( (Bit8u) -1 )
-#define BX_MIN_BIT8U ( 0 )
-#define BX_MAX_BIT8S ( ((Bit8u) -1) >> 1 )
-#define BX_MIN_BIT8S ( -(((Bit8u) -1) >> 1) )
-
-
-// create an unsigned integer type that is the same size as a pointer.
-// You can typecast a pointer to a bx_pr_equiv_t without losing any
-// bits (and without getting the compiler excited). This is used in
-// the FPU emulation code, where pointers and integers are often
-// used interchangeably.
-#if SIZEOF_INT_P == 4
- typedef Bit32u bx_ptr_equiv_t;
-#elif SIZEOF_INT_P == 8
- typedef Bit64u bx_ptr_equiv_t;
-#else
-# error "could not define bx_ptr_equiv_t to size of int*"
-#endif
-
-// Use a boolean type that will not conflict with the builtin type
-// on any system.
-typedef Bit32u bx_bool;
-
-#if BX_WITH_MACOS
-# define bx_ptr_t char *
-#else
-# define bx_ptr_t void *
-#endif
-
-#if defined(WIN32)
-# define BX_LITTLE_ENDIAN
-#elif BX_WITH_MACOS
-# define BX_BIG_ENDIAN
-#else
-#if WORDS_BIGENDIAN
-# define BX_BIG_ENDIAN
-#else
-# define BX_LITTLE_ENDIAN
-#endif
-#endif // defined(WIN32)
-
-
-#if BX_SUPPORT_X86_64
-#ifdef BX_LITTLE_ENDIAN
-typedef
- struct {
- Bit64u lo;
- Bit64u hi;
- } Bit128u;
-typedef
- struct {
- Bit64u lo;
- Bit64s hi;
- } Bit128s;
-#else // must be Big Endian
-typedef
- struct {
- Bit64u hi;
- Bit64u lo;
- } Bit128u;
-typedef
- struct {
- Bit64s hi;
- Bit64u lo;
- } Bit128s;
-#endif
-#endif // #if BX_SUPPORT_X86_64
-
-
-// for now only term.cc requires a GUI sighandler.
-#define BX_GUI_SIGHANDLER (BX_WITH_TERM)
-
-#define HAVE_SIGACTION 1
-
-// configure will change the definition of "inline" to the value
-// that the C compiler allows. It tests the following keywords to
-// see if any is permitted: inline, __inline__, __inline. If none
-// is permitted, it defines inline to be empty.
-#define inline inline
-
-// inline functions in headers that are compiled with C compiler
-// (e.g. fpu code) are declared with BX_C_INLINE macro. Note that
-// the word "inline" itself may now be redefined by the above #define.
-// Many compilers are known to work with "static inline". If the
-// compiler can put the function inline, it does so and never creates
-// a symbol for the function. If optimization is off, or inline is
-// defined to be empty, the static keyword causes the function to create
-// a symbol that's visible only to that .c file. Each .c file that
-// includes the header will produde another local version of the
-// BX_C_INLINE function (not ideal). However without "static" you can
-// duplicate symbol problems which are even worse.
-#define BX_C_INLINE static inline
-
-// Use BX_CPP_INLINE for all C++ inline functions. Note that the
-// word "inline" itself may now be redefined by the above #define.
-#define BX_CPP_INLINE inline
-
-#ifdef __GNUC__
-
-// Some helpful compiler hints for compilers that allow them; GCC for now.
-//
-// BX_CPP_AlignN(n):
-// Align a construct on an n-byte boundary.
-//
-// BX_CPP_AttrPrintf(formatArg, firstArg):
-// This function takes printf-like arguments, so the compiler can check
-// the consistency of the format string and the matching arguments.
-// 'formatArg' is the parameter number (starting from 1) of the format
-// string argument. 'firstArg' is the parameter number of the 1st argument
-// to check against the string argument. NOTE: For non-static member
-// functions, the this-ptr is argument number 1 but is invisible on
-// the function prototype declaration - but you still have to count it.
-//
-// BX_CPP_AttrNoReturn():
-// This function never returns. The compiler can optimize-out following
-// code accordingly.
-
-#define BX_CPP_AlignN(n) __attribute__ ((aligned (n)))
-#define BX_CPP_AttrPrintf(formatArg, firstArg) \
- __attribute__ ((format (printf, formatArg, firstArg)))
-#define BX_CPP_AttrNoReturn() __attribute__ ((noreturn))
-
-#else
-
-#define BX_CPP_AlignN(n) /* Not supported. */
-#define BX_CPP_AttrPrintf(formatArg, firstArg) /* Not supported. */
-#define BX_CPP_AttrNoReturn() /* Not supported. */
-
-#endif
-
-#define BX_DEBUGGER 0
-#define BX_DISASM 0
-
-#define BX_PROVIDE_CPU_MEMORY 1
-#define BX_PROVIDE_DEVICE_MODELS 1
-
-#define BX_SUPPORT_VBE 0
-
-#define BX_PROVIDE_MAIN 1
-
-#define BX_INSTRUMENTATION 0
-
-#define BX_USE_LOADER 0
-
-// for debugger, CPU simulator handle ID
-// 0 is the default, for using only one CPU simulator
-// 1 is for the 2nd CPU simulator
-#define BX_SIM_ID 0
-#define BX_NUM_SIMULATORS 1
-
-// limited i440FX PCI support
-#define BX_PCI_SUPPORT 1
-
-// Experimental VGA on PCI
-#define BX_PCI_VGA_SUPPORT 1
-
-// limited USB on PCI
-#define BX_PCI_USB_SUPPORT 1
-
-#if (BX_PCI_USB_SUPPORT && !BX_PCI_SUPPORT)
-#error To enable USB, you must also enable PCI
-#endif
-
-// Promise VLBIDE DC2300 Support
-#define BX_PDC20230C_VLBIDE_SUPPORT 0
-
-#define BX_SUPPORT_FPU 1
-#define BX_SUPPORT_MMX 1
-#define BX_SUPPORT_3DNOW 0
-#define BX_SUPPORT_SSE 0
-#define BX_SUPPORT_DAZ 0
-#define BX_SUPPORT_PNI 0
-#define BX_SUPPORT_SEP 0
-#define BX_SUPPORT_4MEG_PAGES 0
-
-#define BX_SupportGuest2HostTLB 0
-#define BX_SupportRepeatSpeedups 0
-#define BX_SupportGlobalPages 0
-#define BX_SupportPAE 0
-#define BX_SupportICache 0
-#define BX_SupportHostAsms 1
-
-
-// if 1, don't do gpf on MSRs that we don't implement
-#define BX_IGNORE_BAD_MSR 0
-
-// ========================================================
-// These are some very temporary hacks I made to the 64-bit
-// support to help Peter with debugging etc. They will be removed
-// soon and there is no configure option for them (on purpose).
-// By default, they are not compiled in.
-
-// I set this to 1 to bail in instructions which may not be honoring
-// the 64-bit widths of RIP/RSP. If I trip a panic, then I clean
-// the function up and remove the panic. You don't have to use
-// these.
-#if 0
-#define BailBigRSP(s) \
- if ( (RIP > 0xffffffff) || \
- (RSP > 0xffffffff) ) \
- BX_PANIC((s ": bailing due to big RSP value, mode==%u", \
- BX_CPU_THIS_PTR cpu_mode))
-#else
-#define BailBigRSP(s)
-#endif
-// ========================================================
-
-
-#if (BX_SUPPORT_MMX && BX_CPU_LEVEL < 5)
-#error With CPU level < 5, you must disable MMX support.
-#endif
-
-#if (!BX_SUPPORT_FPU && BX_CPU_LEVEL >= 5)
-#error With CPU level >= 5, you must enable FPU support.
-#endif
-
-#if (BX_SUPPORT_MMX && !BX_SUPPORT_FPU)
-#error "MMX cannot be compiled without FPU support"
-#endif
-
-#if (BX_SUPPORT_3DNOW && !BX_SUPPORT_MMX)
-#error "3DNow! cannot be compiled without MMX support"
-#endif
-
-#if (BX_SUPPORT_SSE && !BX_SUPPORT_MMX)
-#error "SSE cannot be compiled without FPU+MMX support"
-#endif
-
-#if (BX_CPU_LEVEL<6 && BX_SUPPORT_SSE)
-#error SSE is only supported with CPU_LEVEL >= 6
-#endif
-
-#if (BX_SUPPORT_PNI && BX_SUPPORT_SSE <= 1)
-#error "PNI cannot be compiled without SSE/SSE2 support"
-#endif
-
-#if (BX_CPU_LEVEL<6 && BX_SUPPORT_SEP)
-#error SYSENTER/SYSEXIT only supported with CPU_LEVEL >= 6
-#endif
-
-#if BX_SUPPORT_X86_64
-// Sanity checks to ensure that you cannot accidently use conflicting options.
-
-#if BX_CPU_LEVEL < 5
-#error X86-64 requires cpu level 6 or greater
-#endif
-#if (BX_SUPPORT_SSE<2)
-#error X86-64 requires SSE2
-#endif
-#if !BX_SupportPAE
-#error X86-64 requires Physical Address Extensions (PAE)
-#endif
-#if !BX_SupportGlobalPages
-#error X86-64 requires Page Global Extension (PGE)
-#endif
-#if !BX_SUPPORT_4MEG_PAGES
-#error X86-64 requires Page Size Extension (PSE)
-#endif
-
-#if BX_SUPPORT_SEP
-#error SYSENTER/SYSEXIT not implemented for X86-64
-#endif
-
-#endif
-
-#define BX_HAVE_GETENV 1
-#define BX_HAVE_SETENV 1
-#define BX_HAVE_SELECT 1
-#define BX_HAVE_SNPRINTF 1
-#define BX_HAVE_STRTOULL 1
-#define BX_HAVE_STRTOUQ 1
-#define BX_HAVE_STRDUP 1
-#define BX_HAVE_STRREV 0
-#define BX_HAVE_STRUCT_TIMEVAL 1
-
-// used in term gui
-#define BX_HAVE_COLOR_SET 0
-#define BX_HAVE_MVHLINE 0
-#define BX_HAVE_MVVLINE 0
-
-
-// set if your compiler does not permit an empty struct
-#define BX_NO_EMPTY_STRUCTS 0
-
-// set if your compiler does not understand __attribute__ after a struct
-#define BX_NO_ATTRIBUTES 0
-#if BX_NO_ATTRIBUTES
-#define GCC_ATTRIBUTE(x) /* attribute not supported */
-#else
-#define GCC_ATTRIBUTE __attribute__
-#endif
-
-// set to use fast function calls
-#define BX_FAST_FUNC_CALL 0
-
-// On gcc2.95+ x86 only
-#if BX_FAST_FUNC_CALL && defined(__i386__) && defined(__GNUC__) && (__GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95))
-# define BX_CPP_AttrRegparmN(X) __attribute__((regparm(X)))
-#else
-# define BX_CPP_AttrRegparmN(X) /* Not defined */
-#endif
-
-// set if your compiler does not allow label at the end of a {} block
-#define BX_NO_BLANK_LABELS 0
-
-// set if you do have <hash_map>, used in bx_debug/dbg_main.c
-#define BX_HAVE_HASH_MAP 0
-
-// set if you do have <hash_map.h>, used in bx_debug/dbg_main.c
-#define BX_HAVE_HASH_MAP_H 1
-
-// set if you do have <set>, used in bx_debug/dbg_main.c
-#define BX_HAVE_SET 1
-
-// set if you do have <set.h>, used in bx_debug/dbg_main.c
-#define BX_HAVE_SET_H 1
-
-// Support x86 hardware debugger registers and facilites.
-// These are the debug facilites offered by the x86 architecture,
-// not the optional built-in debugger.
-#define BX_X86_DEBUGGER 0
-
-#define BX_SUPPORT_CDROM 1
-
-#if BX_SUPPORT_CDROM
- // This is the C++ class name to use if we are supporting
- // low-level CDROM.
-# define LOWLEVEL_CDROM cdrom_interface
-#endif
-
-// NE2K network emulation
-#define BX_NE2K_SUPPORT 1
-#define BX_ETH_NULL_LOGGING 1
-#define BX_ETH_FBSD_LOGGING 1
-
-// determine which NE2K packet mover modules will be enabled
-// (this was moved from iodev/eth.h)
-#define ETH_NULL 1
-#ifdef BX_USE_ETH_ARPBACK
-# define ETH_ARPBACK 1
-#endif
-#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__)
-#define ETH_FBSD 1
-#endif
-#if defined(linux)
-#define ETH_LINUX 1
-#endif
-#if defined(WIN32)
-#define ETH_WIN32 1
-#endif
-
-// this enables Ethertap packet mover; determined by configure script
-#define HAVE_ETHERTAP 0
-
-// this enables TUN/TAP packet mover; determined by configure script
-#define HAVE_TUNTAP 1
-
-
-// I/O Interface to debug
-#define BX_IODEBUG_SUPPORT 0
-
-// External Debugger
-#define BX_EXTERNAL_DEBUGGER 0
-#define BX_OVERRIDE_ASK 0
-
-#ifdef WIN32
-#define BX_FLOPPY0_NAME "Floppy Disk A:"
-#define BX_FLOPPY1_NAME "Floppy Disk B:"
-#else
-#define BX_FLOPPY0_NAME "Floppy Disk 0"
-#define BX_FLOPPY1_NAME "Floppy Disk 1"
-#endif
-
-// This is handy for certain performance testing purposes, but otherwise
-// totally useless. If you define BX_SCHEDULED_DIE_TIME then it enables code
-// in bx_pit_c::periodic that will cause Bochs to exit() after a certain number
-// of instructions.
-//#define BX_SCHEDULED_DIE_TIME 1162230000 // end of redhat6.0 boot
-
-
-#endif // _BX_CONFIG_H
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: cpu.h,v 1.155 2003/12/30 22:12:45 cbothamy Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2001 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-#ifndef BX_CPU_H
-# define BX_CPU_H 1
-
-#include <setjmp.h>
-#ifdef BX_USE_VMX
-extern "C" {
-#include <io/ioreq.h>
-}
-#endif
-
-
-#if BX_SUPPORT_APIC
-#define BX_CPU_INTR (BX_CPU_THIS_PTR INTR || BX_CPU_THIS_PTR local_apic.INTR)
-#else
-#define BX_CPU_INTR BX_CPU_THIS_PTR INTR
-#endif
-
-class BX_CPU_C;
-class BX_MEM_C;
-
-#if BX_USE_CPU_SMF == 0
-// normal member functions. This can ONLY be used within BX_CPU_C classes.
-// Anyone on the outside should use the BX_CPU macro (defined in bochs.h)
-// instead.
-# define BX_CPU_THIS_PTR this->
-# define BX_CPU_THIS this
-# define BX_SMF
-# define BX_CPU_C_PREFIX BX_CPU_C::
-// with normal member functions, calling a member fn pointer looks like
-// object->*(fnptr)(arg, ...);
-// Since this is different from when SMF=1, encapsulate it in a macro.
-# define BX_CPU_CALL_METHOD(func, args) \
- (this->*((BxExecutePtr_t) (func))) args
-# define BX_CPU_CALL_METHODR(func, args) \
- (this->*((BxExecutePtr_tR) (func))) args
-#else
-// static member functions. With SMF, there is only one CPU by definition.
-# define BX_CPU_THIS_PTR BX_CPU(0)->
-# define BX_CPU_THIS BX_CPU(0)
-# define BX_SMF static
-# define BX_CPU_C_PREFIX
-# define BX_CPU_CALL_METHOD(func, args) \
- ((BxExecutePtr_t) (func)) args
-# define BX_CPU_CALL_METHODR(func, args) \
- ((BxExecutePtr_tR) (func)) args
-#endif
-
-#if BX_SMP_PROCESSORS==1
-// single processor simulation, so there's one of everything
-BOCHSAPI extern BX_CPU_C bx_cpu;
-#else
-// multiprocessor simulation, we need an array of cpus and memories
-BOCHSAPI extern BX_CPU_C *bx_cpu_array[BX_SMP_PROCESSORS];
-#endif
-
-class BOCHSAPI BX_CPU_C : public logfunctions {
-
-public: // for now...
-
- volatile bx_bool async_event;
- volatile bx_bool INTR;
- volatile bx_bool kill_bochs_request;
-
- // constructors & destructors...
- BX_CPU_C();
- ~BX_CPU_C(void);
- void init (BX_MEM_C *addrspace);
- void interrupt(Bit8u vector);
-
- BX_SMF void pagingA20Changed(void);
- BX_SMF void reset(unsigned source);
- BX_SMF void set_INTR(bx_bool value);
- BX_SMF void atexit(void);
-
- // now for some ancillary functions...
- void cpu_loop(Bit32s max_instr_count);
-
-#ifdef BX_USE_VMX
- ioreq_t* __get_ioreq(void);
- ioreq_t* get_ioreq(void);
- void dispatch_ioreq(ioreq_t *req);
- void handle_ioreq();
- void timer_handler();
-
- int send_event;
-#endif
-};
-
-#endif // #ifndef BX_CPU_H
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: extplugin.h,v 1.4 2002/12/12 15:28:37 cbothamy Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// extplugin.h
-//
-// This header file defines the types necessary to make a Bochs plugin,
-// but without mentioning all the details of Bochs internals (bochs.h).
-// It is included by the configuration interfaces and possibly other
-// things which are intentionally isolated from other parts of the program.
-//
-// The plugin_t struct comes from the plugin.h file from plex86.
-// Plex86 is Copyright (C) 1999-2000 The plex86 developers team
-//
-/////////////////////////////////////////////////////////////////////////
-
-#ifndef __EXTPLUGIN_H
-#define __EXTPLUGIN_H
-
-#if BX_PLUGINS
-#include "ltdl.h"
-#endif
-
-enum plugintype_t {
- PLUGTYPE_NULL=100,
- PLUGTYPE_CORE,
- PLUGTYPE_OPTIONAL,
- PLUGTYPE_USER
-};
-
-#define MAX_ARGC 10
-
-typedef struct _plugin_t
-{
- plugintype_t type;
- int initialized;
-#if BX_PLUGINS
- lt_dlhandle handle;
-#endif
- int argc;
- char *name, *args, *argv[MAX_ARGC];
- int (*plugin_init)(struct _plugin_t *plugin, plugintype_t type, int argc, char *argv[]);
- void (*plugin_fini)(void);
-
- struct _plugin_t *next;
-} plugin_t;
-
-
-
-#endif /* __EXTPLUGIN_H */
-
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: instrument.h,v 1.14 2003/10/09 19:05:13 sshwarts Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2001 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-// possible types passed to BX_INSTR_TLB_CNTRL()
-#define BX_INSTR_MOV_CR3 10
-#define BX_INSTR_INVLPG 11
-#define BX_INSTR_TASKSWITCH 12
-
-// possible types passed to BX_INSTR_CACHE_CNTRL()
-#define BX_INSTR_INVD 20
-#define BX_INSTR_WBINVD 21
-
-#define BX_INSTR_IS_CALL 10
-#define BX_INSTR_IS_RET 11
-#define BX_INSTR_IS_IRET 12
-#define BX_INSTR_IS_JMP 13
-#define BX_INSTR_IS_INT 14
-
-#define BX_INSTR_PREFETCH_NTA 00
-#define BX_INSTR_PREFETCH_T0 01
-#define BX_INSTR_PREFETCH_T1 02
-#define BX_INSTR_PREFETCH_T2 03
-
-
-
-
-
-#if BX_INSTRUMENTATION
-
-class bxInstruction_c;
-
-// called from the CPU core
-
-void bx_instr_init(unsigned cpu);
-void bx_instr_shutdown(unsigned cpu);
-void bx_instr_reset(unsigned cpu);
-void bx_instr_new_instruction(unsigned cpu);
-
-void bx_instr_debug_promt();
-void bx_instr_start();
-void bx_instr_stop();
-void bx_instr_print();
-
-void bx_instr_cnear_branch_taken(unsigned cpu, bx_address new_eip);
-void bx_instr_cnear_branch_not_taken(unsigned cpu);
-void bx_instr_ucnear_branch(unsigned cpu, unsigned what, bx_address new_eip);
-void bx_instr_far_branch(unsigned cpu, unsigned what, Bit16u new_cs, bx_address new_eip);
-
-void bx_instr_opcode(unsigned cpu, Bit8u *opcode, unsigned len, bx_bool is32);
-void bx_instr_fetch_decode_completed(unsigned cpu, const bxInstruction_c *i);
-
-void bx_instr_prefix_as(unsigned cpu);
-void bx_instr_prefix_os(unsigned cpu);
-void bx_instr_prefix_rep(unsigned cpu);
-void bx_instr_prefix_repne(unsigned cpu);
-void bx_instr_prefix_lock(unsigned cpu);
-void bx_instr_prefix_cs(unsigned cpu);
-void bx_instr_prefix_ss(unsigned cpu);
-void bx_instr_prefix_ds(unsigned cpu);
-void bx_instr_prefix_es(unsigned cpu);
-void bx_instr_prefix_fs(unsigned cpu);
-void bx_instr_prefix_gs(unsigned cpu);
-void bx_instr_prefix_extend8b(unsigned cpu);
-
-void bx_instr_interrupt(unsigned cpu, unsigned vector);
-void bx_instr_exception(unsigned cpu, unsigned vector);
-void bx_instr_hwinterrupt(unsigned cpu, unsigned vector, Bit16u cs, bx_address eip);
-
-void bx_instr_tlb_cntrl(unsigned cpu, unsigned what, Bit32u newval);
-void bx_instr_cache_cntrl(unsigned cpu, unsigned what);
-void bx_instr_prefetch_hint(unsigned cpu, unsigned what, unsigned seg, bx_address offset);
-
-void bx_instr_before_execution(unsigned cpu);
-void bx_instr_after_execution(unsigned cpu);
-void bx_instr_repeat_iteration(unsigned cpu);
-
-void bx_instr_inp(Bit16u addr, unsigned len);
-void bx_instr_outp(Bit16u addr, unsigned len);
-void bx_instr_inp2(Bit16u addr, unsigned len, unsigned val);
-void bx_instr_outp2(Bit16u addr, unsigned len, unsigned val);
-
-void bx_instr_mem_code(unsigned cpu, bx_address linear, unsigned size);
-void bx_instr_mem_data(unsigned cpu, bx_address linear, unsigned size, unsigned rw);
-
-void bx_instr_lin_read(unsigned cpu, bx_address lin, bx_address phy, unsigned len);
-void bx_instr_lin_write(unsigned cpu, bx_address lin, bx_address phy, unsigned len);
-
-void bx_instr_phy_write(unsigned cpu, bx_address addr, unsigned len);
-void bx_instr_phy_read(unsigned cpu, bx_address addr, unsigned len);
-
-/* simulation init, shutdown, reset */
-# define BX_INSTR_INIT(cpu_id) bx_instr_init(cpu_id)
-# define BX_INSTR_SHUTDOWN(cpu_id) bx_instr_shutdown(cpu_id)
-# define BX_INSTR_RESET(cpu_id) bx_instr_reset(cpu_id)
-# define BX_INSTR_NEW_INSTRUCTION(cpu_id) bx_instr_new_instruction(cpu_id)
-
-/* called from command line debugger */
-# define BX_INSTR_DEBUG_PROMPT() bx_instr_debug_promt()
-# define BX_INSTR_START() bx_instr_start()
-# define BX_INSTR_STOP() bx_instr_stop()
-# define BX_INSTR_PRINT() bx_instr_print()
-
-/* branch resoultion */
-# define BX_INSTR_CNEAR_BRANCH_TAKEN(cpu_id, new_eip) bx_instr_cnear_branch_taken(cpu_id, new_eip)
-# define BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(cpu_id) bx_instr_cnear_branch_not_taken(cpu_id)
-# define BX_INSTR_UCNEAR_BRANCH(cpu_id, what, new_eip) bx_instr_ucnear_branch(cpu_id, what, new_eip)
-# define BX_INSTR_FAR_BRANCH(cpu_id, what, new_cs, new_eip) bx_instr_far_branch(cpu_id, what, new_cs, new_eip)
-
-/* decoding completed */
-# define BX_INSTR_OPCODE(cpu_id, opcode, len, is32) \
- bx_instr_opcode(cpu_id, opcode, len, is32)
-# define BX_INSTR_FETCH_DECODE_COMPLETED(cpu_id, i) \
- bx_instr_fetch_decode_completed(cpu_id, i)
-
-/* prefix decoded */
-# define BX_INSTR_PREFIX_AS(cpu_id) bx_instr_prefix_as(cpu_id)
-# define BX_INSTR_PREFIX_OS(cpu_id) bx_instr_prefix_os(cpu_id)
-# define BX_INSTR_PREFIX_REP(cpu_id) bx_instr_prefix_rep(cpu_id)
-# define BX_INSTR_PREFIX_REPNE(cpu_id) bx_instr_prefix_repne(cpu_id)
-# define BX_INSTR_PREFIX_LOCK(cpu_id) bx_instr_prefix_lock(cpu_id)
-# define BX_INSTR_PREFIX_CS(cpu_id) bx_instr_prefix_cs(cpu_id)
-# define BX_INSTR_PREFIX_SS(cpu_id) bx_instr_prefix_ss(cpu_id)
-# define BX_INSTR_PREFIX_DS(cpu_id) bx_instr_prefix_ds(cpu_id)
-# define BX_INSTR_PREFIX_ES(cpu_id) bx_instr_prefix_es(cpu_id)
-# define BX_INSTR_PREFIX_FS(cpu_id) bx_instr_prefix_fs(cpu_id)
-# define BX_INSTR_PREFIX_GS(cpu_id) bx_instr_prefix_gs(cpu_id)
-# define BX_INSTR_PREFIX_EXTEND8B(cpu_id) bx_instr_prefix_extend8b(cpu_id)
-
-/* exceptional case and interrupt */
-# define BX_INSTR_EXCEPTION(cpu_id, vector) bx_instr_exception(cpu_id, vector)
-# define BX_INSTR_INTERRUPT(cpu_id, vector) bx_instr_interrupt(cpu_id, vector)
-# define BX_INSTR_HWINTERRUPT(cpu_id, vector, cs, eip) bx_instr_hwinterrupt(cpu_id, vector, cs, eip)
-
-/* TLB/CACHE control instruction executed */
-# define BX_INSTR_CACHE_CNTRL(cpu_id, what) bx_instr_cache_cntrl(cpu_id, what)
-# define BX_INSTR_TLB_CNTRL(cpu_id, what, newval) bx_instr_tlb_cntrl(cpu_id, what, newval)
-# define BX_INSTR_PREFETCH_HINT(cpu_id, what, seg, offset) \
- bx_instr_prefetch_hint(cpu_id, what, seg, offset)
-
-/* execution */
-# define BX_INSTR_BEFORE_EXECUTION(cpu_id) bx_instr_before_execution(cpu_id)
-# define BX_INSTR_AFTER_EXECUTION(cpu_id) bx_instr_after_execution(cpu_id)
-# define BX_INSTR_REPEAT_ITERATION(cpu_id) bx_instr_repeat_iteration(cpu_id)
-
-/* memory access */
-# define BX_INSTR_LIN_READ(cpu_id, lin, phy, len) bx_instr_lin_read(cpu_id, lin, phy, len)
-# define BX_INSTR_LIN_WRITE(cpu_id, lin, phy, len) bx_instr_lin_write(cpu_id, lin, phy, len)
-
-# define BX_INSTR_MEM_CODE(cpu_id, linear, size) bx_instr_mem_code(cpu_id, linear, size)
-# define BX_INSTR_MEM_DATA(cpu_id, linear, size, rw) bx_instr_mem_data(cpu_id, linear, size, rw)
-
-/* called from memory object */
-# define BX_INSTR_PHY_WRITE(cpu_id, addr, len) bx_instr_phy_write(cpu_id, addr, len)
-# define BX_INSTR_PHY_READ(cpu_id, addr, len) bx_instr_phy_read(cpu_id, addr, len)
-
-/* feedback from device units */
-# define BX_INSTR_INP(addr, len) bx_instr_inp(addr, len)
-# define BX_INSTR_INP2(addr, len, val) bx_instr_inp2(addr, len, val)
-# define BX_INSTR_OUTP(addr, len) bx_instr_outp(addr, len)
-# define BX_INSTR_OUTP2(addr, len, val) bx_instr_outp2(addr, len, val)
-
-#else
-
-/* simulation init, shutdown, reset */
-# define BX_INSTR_INIT(cpu_id)
-# define BX_INSTR_SHUTDOWN(cpu_id)
-# define BX_INSTR_RESET(cpu_id)
-# define BX_INSTR_NEW_INSTRUCTION(cpu_id)
-
-/* called from command line debugger */
-# define BX_INSTR_DEBUG_PROMPT()
-# define BX_INSTR_START()
-# define BX_INSTR_STOP()
-# define BX_INSTR_PRINT()
-
-/* branch resoultion */
-# define BX_INSTR_CNEAR_BRANCH_TAKEN(cpu_id, new_eip)
-# define BX_INSTR_CNEAR_BRANCH_NOT_TAKEN(cpu_id)
-# define BX_INSTR_UCNEAR_BRANCH(cpu_id, what, new_eip)
-# define BX_INSTR_FAR_BRANCH(cpu_id, what, new_cs, new_eip)
-
-/* decoding completed */
-# define BX_INSTR_OPCODE(cpu_id, opcode, len, is32)
-# define BX_INSTR_FETCH_DECODE_COMPLETED(cpu_id, i)
-
-/* prefix decoded */
-# define BX_INSTR_PREFIX_AS(cpu_id)
-# define BX_INSTR_PREFIX_OS(cpu_id)
-# define BX_INSTR_PREFIX_REP(cpu_id)
-# define BX_INSTR_PREFIX_REPNE(cpu_id)
-# define BX_INSTR_PREFIX_LOCK(cpu_id)
-# define BX_INSTR_PREFIX_CS(cpu_id)
-# define BX_INSTR_PREFIX_SS(cpu_id)
-# define BX_INSTR_PREFIX_DS(cpu_id)
-# define BX_INSTR_PREFIX_ES(cpu_id)
-# define BX_INSTR_PREFIX_FS(cpu_id)
-# define BX_INSTR_PREFIX_GS(cpu_id)
-# define BX_INSTR_PREFIX_EXTEND8B(cpu_id)
-
-/* exceptional case and interrupt */
-# define BX_INSTR_EXCEPTION(cpu_id, vector)
-# define BX_INSTR_INTERRUPT(cpu_id, vector)
-# define BX_INSTR_HWINTERRUPT(cpu_id, vector, cs, eip)
-
-/* TLB/CACHE control instruction executed */
-# define BX_INSTR_CACHE_CNTRL(cpu_id, what)
-# define BX_INSTR_TLB_CNTRL(cpu_id, what, newval)
-# define BX_INSTR_PREFETCH_HINT(cpu_id, what, seg, offset)
-
-/* execution */
-# define BX_INSTR_BEFORE_EXECUTION(cpu_id)
-# define BX_INSTR_AFTER_EXECUTION(cpu_id)
-# define BX_INSTR_REPEAT_ITERATION(cpu_id)
-
-/* memory access */
-# define BX_INSTR_LIN_READ(cpu_id, lin, phy, len)
-# define BX_INSTR_LIN_WRITE(cpu_id, lin, phy, len)
-
-# define BX_INSTR_MEM_CODE(cpu_id, linear, size)
-# define BX_INSTR_MEM_DATA(cpu_id, linear, size, rw)
-
-/* called from memory object */
-# define BX_INSTR_PHY_WRITE(cpu_id, addr, len)
-# define BX_INSTR_PHY_READ(cpu_id, addr, len)
-
-/* feedback from device units */
-# define BX_INSTR_INP(addr, len)
-# define BX_INSTR_INP2(addr, len, val)
-# define BX_INSTR_OUTP(addr, len)
-# define BX_INSTR_OUTP2(addr, len, val)
-
-#endif
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: ltdl.h,v 1.2 2002/10/24 21:04:37 bdenney Exp $
-//
-// NOTE: The ltdl library comes from the Libtool package. Bochs uses
-// ltdl and libtool to build and load plugins. The libtool
-// documentation describes how to copy ltdl.c and ltdl.h into your
-// distribution, so it is clearly legal to do so.
-/////////////////////////////////////////////////////////////////////////
-
-/* ltdl.h -- generic dlopen functions
- Copyright (C) 1998-2000 Free Software Foundation, Inc.
- Originally by Thomas Tanner <tanner@ffii.org>
- This file is part of GNU Libtool.
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2 of the License, or (at your option) any later version.
-
-As a special exception to the GNU Lesser General Public License,
-if you distribute this file as part of a program or library that
-is built using GNU libtool, you may include it under the same
-distribution terms that you use for the rest of that program.
-
-This library is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free
-Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-02111-1307 USA
-*/
-
-/* Only include this header file once. */
-#ifndef LTDL_H
-#define LTDL_H 1
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-#include <sys/types.h> /* for size_t declaration */
-#ifdef __cplusplus
-};
-#endif
-
-\f
-/* --- MACROS FOR PORTABILITY --- */
-
-
-/* Saves on those hard to debug '\0' typos.... */
-#define LT_EOS_CHAR '\0'
-
-/* LTDL_BEGIN_C_DECLS should be used at the beginning of your declarations,
- so that C++ compilers don't mangle their names. Use LTDL_END_C_DECLS at
- the end of C declarations. */
-#ifdef __cplusplus
-# define LT_BEGIN_C_DECLS extern "C" {
-# define LT_END_C_DECLS }
-#else
-# define LT_BEGIN_C_DECLS /* empty */
-# define LT_END_C_DECLS /* empty */
-#endif
-
-LT_BEGIN_C_DECLS
-
-
-/* LT_PARAMS is a macro used to wrap function prototypes, so that compilers
- that don't understand ANSI C prototypes still work, and ANSI C
- compilers can issue warnings about type mismatches. */
-#if defined (__STDC__) || defined (_AIX) || (defined (__mips) && defined (_SYSTYPE_SVR4)) || defined(WIN32) || defined(__cplusplus)
-# define LT_PARAMS(protos) protos
-# define lt_ptr void*
-#else
-# define LT_PARAMS(protos) ()
-# define lt_ptr char*
-#endif
-
-/* LT_STMT_START/END are used to create macros which expand to a
- a single compound statement in a portable way. */
-#if defined (__GNUC__) && !defined (__STRICT_ANSI__) && !defined (__cplusplus)
-# define LT_STMT_START (void)(
-# define LT_STMT_END )
-#else
-# if (defined (sun) || defined (__sun__))
-# define LT_STMT_START if (1)
-# define LT_STMT_END else (void)0
-# else
-# define LT_STMT_START do
-# define LT_STMT_END while (0)
-# endif
-#endif
-
-/* LT_CONC creates a new concatenated symbol for the compiler
- in a portable way. */
-#if defined(__STDC__) || defined(__cplusplus)
-# define LT_CONC(s,t) s##t
-#else
-# define LT_CONC(s,t) s/**/t
-#endif
-
-/* LT_STRLEN can be used safely on NULL pointers. */
-#define LT_STRLEN(s) (((s) && (s)[0]) ? strlen (s) : 0)
-
-
-\f
-/* --- WINDOWS SUPPORT --- */
-
-
-/* Canonicalise Windows and Cygwin recognition macros. */
-#ifdef __CYGWIN32__
-# ifndef __CYGWIN__
-# define __CYGWIN__ __CYGWIN32__
-# endif
-#endif
-#if defined(_WIN32) || defined(WIN32)
-# ifndef __WINDOWS__
-# ifdef _WIN32
-# define __WINDOWS__ _WIN32
-# else
-# ifdef WIN32
-# define __WINDOWS__ WIN32
-# endif
-# endif
-# endif
-#endif
-
-#ifdef __WINDOWS__
-# ifndef __CYGWIN__
-/* LT_DIRSEP_CHAR is accepted *in addition* to '/' as a directory
- separator when it is set. */
-# define LT_DIRSEP_CHAR '\\'
-# define LT_PATHSEP_CHAR ';'
-# endif
-#endif
-#ifndef LT_PATHSEP_CHAR
-# define LT_PATHSEP_CHAR ':'
-#endif
-
-/* DLL building support on win32 hosts; mostly to workaround their
- ridiculous implementation of data symbol exporting. */
-#ifndef LT_SCOPE
-# ifdef __WINDOWS__
-# ifdef DLL_EXPORT /* defined by libtool (if required) */
-# define LT_SCOPE __declspec(dllexport)
-# endif
-# ifdef LIBLTDL_DLL_IMPORT /* define if linking with this dll */
-# define LT_SCOPE extern __declspec(dllimport)
-# endif
-# endif
-# ifndef LT_SCOPE /* static linking or !__WINDOWS__ */
-# define LT_SCOPE extern
-# endif
-#endif
-
-
-
-\f
-/* --- DYNAMIC MODULE LOADING API --- */
-
-
-typedef struct lt_dlhandle_struct *lt_dlhandle; /* A loaded module. */
-
-/* Initialisation and finalisation functions for libltdl. */
-extern int lt_dlinit LT_PARAMS((void));
-extern int lt_dlexit LT_PARAMS((void));
-
-/* Module search path manipulation. */
-extern int lt_dladdsearchdir LT_PARAMS((const char *search_dir));
-extern int lt_dlinsertsearchdir LT_PARAMS((const char *before,
- const char *search_dir));
-extern int lt_dlsetsearchpath LT_PARAMS((const char *search_path));
-extern const char *lt_dlgetsearchpath LT_PARAMS((void));
-extern int lt_dlforeachfile LT_PARAMS((
- const char *search_path,
- int (*func) (const char *filename, lt_ptr data),
- lt_ptr data));
-
-/* Portable libltdl versions of the system dlopen() API. */
-extern lt_dlhandle lt_dlopen LT_PARAMS((const char *filename));
-extern lt_dlhandle lt_dlopenext LT_PARAMS((const char *filename));
-extern lt_ptr lt_dlsym LT_PARAMS((lt_dlhandle handle,
- const char *name));
-extern const char *lt_dlerror LT_PARAMS((void));
-extern int lt_dlclose LT_PARAMS((lt_dlhandle handle));
-
-/* Module residency management. */
-extern int lt_dlmakeresident LT_PARAMS((lt_dlhandle handle));
-extern int lt_dlisresident LT_PARAMS((lt_dlhandle handle));
-
-
-
-\f
-/* --- MUTEX LOCKING --- */
-
-
-typedef void lt_dlmutex_lock LT_PARAMS((void));
-typedef void lt_dlmutex_unlock LT_PARAMS((void));
-typedef void lt_dlmutex_seterror LT_PARAMS((const char *errmsg));
-typedef const char *lt_dlmutex_geterror LT_PARAMS((void));
-
-extern int lt_dlmutex_register LT_PARAMS((lt_dlmutex_lock *lock,
- lt_dlmutex_unlock *unlock,
- lt_dlmutex_seterror *seterror,
- lt_dlmutex_geterror *geterror));
-
-
-
-\f
-/* --- MEMORY HANDLING --- */
-
-
-/* By default, the realloc function pointer is set to our internal
- realloc implementation which iself uses lt_dlmalloc and lt_dlfree.
- libltdl relies on a featureful realloc, but if you are sure yours
- has the right semantics then you can assign it directly. Generally,
- it is safe to assign just a malloc() and a free() function. */
-LT_SCOPE lt_ptr (*lt_dlmalloc) LT_PARAMS((size_t size));
-LT_SCOPE lt_ptr (*lt_dlrealloc) LT_PARAMS((lt_ptr ptr, size_t size));
-LT_SCOPE void (*lt_dlfree) LT_PARAMS((lt_ptr ptr));
-
-
-
-\f
-/* --- PRELOADED MODULE SUPPORT --- */
-
-
-/* A preopened symbol. Arrays of this type comprise the exported
- symbols for a dlpreopened module. */
-typedef struct {
- const char *name;
- lt_ptr address;
-} lt_dlsymlist;
-
-extern int lt_dlpreload LT_PARAMS((const lt_dlsymlist *preloaded));
-extern int lt_dlpreload_default
- LT_PARAMS((const lt_dlsymlist *preloaded));
-
-#define LTDL_SET_PRELOADED_SYMBOLS() LT_STMT_START{ \
- extern const lt_dlsymlist lt_preloaded_symbols[]; \
- lt_dlpreload_default(lt_preloaded_symbols); \
- }LT_STMT_END
-
-
-
-\f
-/* --- MODULE INFORMATION --- */
-
-
-/* Read only information pertaining to a loaded module. */
-typedef struct {
- char *filename; /* file name */
- char *name; /* module name */
- int ref_count; /* number of times lt_dlopened minus
- number of times lt_dlclosed. */
-} lt_dlinfo;
-
-extern const lt_dlinfo *lt_dlgetinfo LT_PARAMS((lt_dlhandle handle));
-extern lt_dlhandle lt_dlhandle_next LT_PARAMS((lt_dlhandle place));
-extern int lt_dlforeach LT_PARAMS((
- int (*func) (lt_dlhandle handle, lt_ptr data),
- lt_ptr data));
-
-/* Associating user data with loaded modules. */
-typedef unsigned lt_dlcaller_id;
-
-extern lt_dlcaller_id lt_dlcaller_register LT_PARAMS((void));
-extern lt_ptr lt_dlcaller_set_data LT_PARAMS((lt_dlcaller_id key,
- lt_dlhandle handle,
- lt_ptr data));
-extern lt_ptr lt_dlcaller_get_data LT_PARAMS((lt_dlcaller_id key,
- lt_dlhandle handle));
-
-
-\f
-/* --- USER MODULE LOADER API --- */
-
-
-typedef struct lt_dlloader lt_dlloader;
-typedef lt_ptr lt_user_data;
-typedef lt_ptr lt_module;
-
-/* Function pointer types for creating user defined module loaders. */
-typedef lt_module lt_module_open LT_PARAMS((lt_user_data loader_data,
- const char *filename));
-typedef int lt_module_close LT_PARAMS((lt_user_data loader_data,
- lt_module handle));
-typedef lt_ptr lt_find_sym LT_PARAMS((lt_user_data loader_data,
- lt_module handle,
- const char *symbol));
-typedef int lt_dlloader_exit LT_PARAMS((lt_user_data loader_data));
-
-struct lt_user_dlloader {
- const char *sym_prefix;
- lt_module_open *module_open;
- lt_module_close *module_close;
- lt_find_sym *find_sym;
- lt_dlloader_exit *dlloader_exit;
- lt_user_data dlloader_data;
-};
-
-extern lt_dlloader *lt_dlloader_next LT_PARAMS((lt_dlloader *place));
-extern lt_dlloader *lt_dlloader_find LT_PARAMS((
- const char *loader_name));
-extern const char *lt_dlloader_name LT_PARAMS((lt_dlloader *place));
-extern lt_user_data *lt_dlloader_data LT_PARAMS((lt_dlloader *place));
-extern int lt_dlloader_add LT_PARAMS((lt_dlloader *place,
- const struct lt_user_dlloader *dlloader,
- const char *loader_name));
-extern int lt_dlloader_remove LT_PARAMS((
- const char *loader_name));
-
-
-\f
-/* --- ERROR MESSAGE HANDLING --- */
-
-/* Bryce rewrote the error table in a way that would be likely to work
- on all compilers. VC++ was not able to handle it the way it was
- done originally. */
-
-/* ORIG COMMENT: Defining error strings alongside their symbolic names in a
- macro in this way allows us to expand the macro in different contexts with
- confidence that the enumeration of symbolic names will map correctly
- onto the table of error strings. */
-
-#define lt_dlerror_symbols_list \
- LT_ERROR_UNKNOWN, \
- LT_ERROR_DLOPEN_NOT_SUPPORTED, \
- LT_ERROR_INVALID_LOADER, \
- LT_ERROR_INIT_LOADER, \
- LT_ERROR_REMOVE_LOADER, \
- LT_ERROR_FILE_NOT_FOUND, \
- LT_ERROR_DEPLIB_NOT_FOUND, \
- LT_ERROR_NO_SYMBOLS, \
- LT_ERROR_CANNOT_OPEN, \
- LT_ERROR_CANNOT_CLOSE, \
- LT_ERROR_SYMBOL_NOT_FOUND, \
- LT_ERROR_NO_MEMORY, \
- LT_ERROR_INVALID_HANDLE, \
- LT_ERROR_BUFFER_OVERFLOW, \
- LT_ERROR_INVALID_ERRORCODE, \
- LT_ERROR_SHUTDOWN, \
- LT_ERROR_CLOSE_RESIDENT_MODULE, \
- LT_ERROR_INVALID_MUTEX_ARGS, \
- LT_ERROR_INVALID_POSITION,
-
-#define lt_dlerror_names_list \
- "unknown error", \
- "dlopen support not available", \
- "invalid loader", \
- "loader initialization failed", \
- "loader removal failed", \
- "file not found", \
- "dependency library not found", \
- "no symbols defined", \
- "can't open the module", \
- "can't close the module", \
- "symbol not found", \
- "not enough memory", \
- "invalid module handle", \
- "internal buffer overflow", \
- "invalid errorcode", \
- "library already shutdown", \
- "can't close resident module", \
- "invalid mutex handler registration", \
- "invalid search path insert position",
-
-/* Enumerate the symbolic error names. */
-enum {
- lt_dlerror_symbols_list
- LT_ERROR_MAX
-};
-
-/* These functions are only useful from inside custom module loaders. */
-extern int lt_dladderror LT_PARAMS((const char *diagnostic));
-extern int lt_dlseterror LT_PARAMS((int errorcode));
-
-
-
-\f
-/* --- SOURCE COMPATIBILITY WITH OLD LIBLTDL --- */
-
-
-#ifdef LT_NON_POSIX_NAMESPACE
-# define lt_ptr_t lt_ptr
-# define lt_module_t lt_module
-# define lt_module_open_t lt_module_open
-# define lt_module_close_t lt_module_close
-# define lt_find_sym_t lt_find_sym
-# define lt_dlloader_exit_t lt_dlloader_exit
-# define lt_dlloader_t lt_dlloader
-# define lt_dlloader_data_t lt_user_data
-#endif
-
-LT_END_C_DECLS
-
-#endif /* !LTDL_H */
+++ /dev/null
-/* ltdlconf.h. Generated by configure. */
-/////////////////////////////////////////////////////////////////////////
-// $Id: ltdlconf.h.in,v 1.2 2002/10/24 21:04:38 bdenney Exp $
-//
-// The configure script reads this file and produces ltdlconf.h, which
-// tells ltdl.c how to compile. It was copied out of the libtool package
-// but appears to have been generated by autoheader.
-/////////////////////////////////////////////////////////////////////////
-
-/* config-h.in. Generated automatically from configure.in by autoheader. */
-
-/* Define to empty if the keyword does not work. */
-/* #undef const */
-
-/* Define as __inline if that's what the C compiler calls it. */
-/* #undef inline */
-
-/* Define if you have the ANSI C header files. */
-#define STDC_HEADERS 1
-
-/* Define if you have the argz_append function. */
-#define HAVE_ARGZ_APPEND 1
-
-/* Define if you have the argz_create_sep function. */
-#define HAVE_ARGZ_CREATE_SEP 1
-
-/* Define if you have the argz_insert function. */
-#define HAVE_ARGZ_INSERT 1
-
-/* Define if you have the argz_next function. */
-#define HAVE_ARGZ_NEXT 1
-
-/* Define if you have the argz_stringify function. */
-#define HAVE_ARGZ_STRINGIFY 1
-
-/* Define if you have the bcopy function. */
-/* #undef HAVE_BCOPY */
-
-/* Define if you have the dlerror function. */
-#define HAVE_DLERROR 1
-
-/* Define if you have the index function. */
-/* #undef HAVE_INDEX */
-
-/* Define if you have the memcpy function. */
-#define HAVE_MEMCPY 1
-
-/* Define if you have the memmove function. */
-#define HAVE_MEMMOVE 1
-
-/* Define if you have the rindex function. */
-/* #undef HAVE_RINDEX */
-
-/* Define if you have the strchr function. */
-#define HAVE_STRCHR 1
-
-/* Define if you have the strcmp function. */
-#define HAVE_STRCMP 1
-
-/* Define if you have the strrchr function. */
-#define HAVE_STRRCHR 1
-
-/* Define if you have the <argz.h> header file. */
-#define HAVE_ARGZ_H 1
-
-/* Define if you have the <assert.h> header file. */
-#define HAVE_ASSERT_H 1
-
-/* Define if you have the <ctype.h> header file. */
-#define HAVE_CTYPE_H 1
-
-/* Define if you have the <dirent.h> header file. */
-#define HAVE_DIRENT_H 1
-
-/* Define if you have the <dl.h> header file. */
-/* #undef HAVE_DL_H */
-
-/* Define if you have the <dld.h> header file. */
-/* #undef HAVE_DLD_H */
-
-/* Define if you have the <dlfcn.h> header file. */
-#define HAVE_DLFCN_H 1
-
-/* Define if you have the <errno.h> header file. */
-#define HAVE_ERRNO_H 1
-
-/* Define if you have the <malloc.h> header file. */
-#define HAVE_MALLOC_H 1
-
-/* Define if you have the <memory.h> header file. */
-#define HAVE_MEMORY_H 1
-
-/* Define if you have the <ndir.h> header file. */
-/* #undef HAVE_NDIR_H */
-
-/* Define if you have the <stdio.h> header file. */
-#define HAVE_STDIO_H 1
-
-/* Define if you have the <stdlib.h> header file. */
-#define HAVE_STDLIB_H 1
-
-/* Define if you have the <string.h> header file. */
-#define HAVE_STRING_H 1
-
-/* Define if you have the <strings.h> header file. */
-#define HAVE_STRINGS_H 1
-
-/* Define if you have the <sys/dir.h> header file. */
-/* #undef HAVE_SYS_DIR_H */
-
-/* Define if you have the <sys/dl.h> header file. */
-/* #undef HAVE_SYS_DL_H */
-
-/* Define if you have the <sys/ndir.h> header file. */
-/* #undef HAVE_SYS_NDIR_H */
-
-/* Define if you have the <unistd.h> header file. */
-#define HAVE_UNISTD_H 1
-
-/* Define to the extension used for shared libraries, say, .so. */
-#define LTDL_SHLIB_EXT ".so"
-
-/* Define to the name of the environment variable that determines the dynamic library search path. */
-#define LTDL_SHLIBPATH_VAR "LD_LIBRARY_PATH"
-
-/* Define to the system default library search path. */
-#define LTDL_SYSSEARCHPATH "/lib:/usr/lib"
-
-/* Define to the sub-directory in which libtool stores uninstalled libraries. */
-#define LTDL_OBJDIR ".libs/"
-
-/* Define if libtool can extract symbol lists from object files. */
-#define HAVE_PRELOADED_SYMBOLS 1
-
-/* Define if you have the libdl library or equivalent. */
-#define HAVE_LIBDL 1
-
-/* Define if you have the libdl library or equivalent. */
-#define HAVE_LIBDL 1
-
-/* Define if you have the libdl library or equivalent. */
-#define HAVE_LIBDL 1
-
-/* Define if you have the shl_load function. */
-/* #undef HAVE_SHL_LOAD */
-
-/* Define if you have the shl_load function. */
-/* #undef HAVE_SHL_LOAD */
-
-/* Define if you have the GNU dld library. */
-/* #undef HAVE_DLD */
-
-/* Define if dlsym() requires a leading underscode in symbol names. */
-/* #undef NEED_USCORE */
-
-/* Define if the OS needs help to load dependent libraries for dlopen(). */
-/* #undef LTDL_DLOPEN_DEPLIBS */
-
-/* Define to a type to use for `error_t' if it is not otherwise available. */
-/* #undef error_t */
-
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: osdep.h,v 1.19 2003/08/20 06:26:27 japj Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2001 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-//
-// osdep.h
-//
-// requires Bit32u/Bit64u from config.h, size_t from stdio.h
-//
-// Operating system dependent includes and defines for Bochs. These
-// declarations can be included by C or C++., but they require definition of
-// size_t beforehand. This makes it difficult to place them into either
-// config.h or bochs.h. If in config.h, size_t is not always available yet.
-// If in bochs.h, they can't be included by C programs so they lose.
-//
-
-#ifndef BX_OSDEP_H
-#define BX_OSDEP_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-//////////////////////////////////////////////////////////////////////
-// Hacks for win32, but exclude MINGW32 because it doesn't need them.
-//////////////////////////////////////////////////////////////////////
-#ifdef WIN32
-
-// Definitions that are needed for all WIN32 compilers.
-# define ssize_t long
-
-#ifndef __MINGW32__
-#define FMT_LL "%I64"
-
-// Definitions that are needed for WIN32 compilers EXCEPT FOR
-// cygwin compiling with -mno-cygwin. e.g. VC++.
-
-// always return regular file.
-# define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
-# define S_ISCHR(m) (((m) & S_IFMT) == S_IFCHR)
-
-// win32 has snprintf though with different name.
-#define snprintf _snprintf
-#else /* ifnndef __MINGW32__ */
-#define FMT_LL "%ll"
-#endif /* ifnndef __MINGW32__ */
-#else /* WIN32 */
-#define FMT_LL "%ll"
-#endif /* WIN32 */
-
-// Missing defines for open
-#ifndef S_IRUSR
-#define S_IRUSR 0400
-#define S_IWUSR 0200
-#endif
-#ifndef S_IRGRP
-#define S_IRGRP 0040
-#define S_IWGRP 0020
-#endif
-#ifndef S_IROTH
-#define S_IROTH 0004
-#define S_IWOTH 0002
-#endif
-
-//////////////////////////////////////////////////////////////////////
-// Missing library functions.
-// These should work on any platform that needs them.
-//
-// A missing library function is renamed to a bx_* function, so that when
-// debugging and linking there's no confusion over which version is used.
-// Because of renaming, the bx_* replacement functions can be tested on
-// machines which have the real library function without duplicate symbols.
-//
-// If you're considering implementing a missing library function, note
-// that it might be cleaner to conditionally disable the function call!
-//////////////////////////////////////////////////////////////////////
-
-#if !BX_HAVE_SNPRINTF
-#define snprintf bx_snprintf
- extern int bx_snprintf (char *s, size_t maxlen, const char *format, ...);
-#endif
-
-#if BX_HAVE_STRTOULL
- // great, just use the usual function
-#elif BX_HAVE_STRTOUQ
- // they have strtouq and not strtoull
- #define strtoull strtouq
-#else
- #define strtoull bx_strtoull
- extern Bit64u bx_strtoull (const char *nptr, char **endptr, int baseignore);
-#endif
-
-#if !BX_HAVE_STRDUP
-#define strdup bx_strdup
- extern char *bx_strdup(const char *str);
-#endif
-
-#if !BX_HAVE_STRREV
-#define strrev bx_strrev
- extern char *bx_strrev(char *str);
-#endif
-
-#if !BX_HAVE_SOCKLEN_T
-// needed on MacOS X 10.1
-typedef int socklen_t;
-#endif
-
-#if !BX_HAVE_MKSTEMP
-#define mkstemp bx_mkstemp
- extern int bx_mkstemp(char *tpl);
-#endif
-
-//////////////////////////////////////////////////////////////////////
-// Missing library functions, implemented for MacOS only
-//////////////////////////////////////////////////////////////////////
-
-#if BX_WITH_MACOS
-// fd_read and fd_write are called by floppy.cc to access the Mac
-// floppy drive directly, since the MacOS doesn't have "special"
-// pathnames which map directly to IO devices
-
-int fd_read(char *buffer, Bit32u offset, Bit32u bytes);
-int fd_write(char *buffer, Bit32u offset, Bit32u bytes);
-int fd_stat(struct stat *buf);
-FILE * fdopen(int fd, const char *type);
-
-typedef long ssize_t ;
-#endif
-
-//////////////////////////////////////////////////////////////////////
-// New functions to replace library functions
-// with OS-independent versions
-//////////////////////////////////////////////////////////////////////
-
-#if BX_HAVE_REALTIME_USEC
-// 64-bit time in useconds.
-extern Bit64u bx_get_realtime64_usec (void);
-#endif
-
-#ifdef WIN32
-#undef BX_HAVE_MSLEEP
-#define BX_HAVE_MSLEEP 1
-#ifndef __MINGW32__
-#define msleep(msec) _sleep(msec)
-#else
-#define msleep(msec) Sleep(msec)
-#endif
-#endif
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-#endif /* ifdef BX_OSDEP_H */
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: pc_system.h,v 1.25 2003/03/02 23:59:08 cbothamy Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-
-
-#define BX_MAX_TIMERS 64
-#define BX_NULL_TIMER_HANDLE 10000
-
-
-#if BX_SHOW_IPS
-extern unsigned long ips_count;
-#endif
-
-
-typedef void (*bx_timer_handler_t)(void *);
-
-
-BOCHSAPI extern class bx_pc_system_c bx_pc_system;
-
-#ifdef PROVIDE_M_IPS
-extern double m_ips;
-#endif
-
-#ifdef BX_USE_VMX
-extern unsigned int tsc_per_bx_tick;
-
-#define rdtscll(val) \
- __asm__ __volatile__("rdtsc" : "=A" (val))
-#endif
-
-class BOCHSAPI bx_pc_system_c : private logfunctions {
-private:
-
- // ===============================
- // Timer oriented private features
- // ===============================
-
- struct {
- bx_bool inUse; // Timer slot is in-use (currently registered).
- Bit64u period; // Timer periodocity in cpu ticks.
- Bit64u timeToFire; // Time to fire next (in absolute ticks).
- bx_bool active; // 0=inactive, 1=active.
- bx_bool continuous; // 0=one-shot timer, 1=continuous periodicity.
- bx_timer_handler_t funct; // A callback function for when the
- // timer fires.
- void *this_ptr; // The this-> pointer for C++ callbacks
- // has to be stored as well.
-#define BxMaxTimerIDLen 32
- char id[BxMaxTimerIDLen]; // String ID of timer.
- } timer[BX_MAX_TIMERS];
-
- unsigned numTimers; // Number of currently allocated timers.
- Bit32u currCountdown; // Current countdown ticks value (decrements to 0).
- Bit32u currCountdownPeriod; // Length of current countdown period.
- Bit64u ticksTotal; // Num ticks total since start of emulator execution.
- Bit64u lastTimeUsec; // Last sequentially read time in usec.
- Bit64u usecSinceLast; // Number of useconds claimed since then.
-
- // A special null timer is always inserted in the timer[0] slot. This
- // make sure that at least one timer is always active, and that the
- // duration is always less than a maximum 32-bit integer, so a 32-bit
- // counter can be used for the current countdown.
- static const Bit64u NullTimerInterval;
- static void nullTimer(void* this_ptr);
-
-#if !defined(PROVIDE_M_IPS)
- // This is the emulator speed, as measured in millions of
- // x86 instructions per second that it can emulate on some hypothetically
- // nomimal workload.
- double m_ips; // Millions of Instructions Per Second
-#endif
-
-#ifdef BX_USE_VMX
- static Bit64s get_clock(void) {
- struct timeval tv;
- gettimeofday(&tv, NULL);
- return tv.tv_sec * 1000000LL + tv.tv_usec;
- }
-
- static Bit64u cpu_calibrate_ticks(void) {
- Bit64s usec, t1, t2;
-
- usec = get_clock();
- rdtscll(t1);
-
- usleep(50 * 1000);
- usec = get_clock() - usec;
- rdtscll(t2);
-
- return (((t2 - t1) * 1000000LL + (usec >> 1)) / usec);
- }
-#endif
- // This handler is called when the function which decrements the clock
- // ticks finds that an event has occurred.
- void countdownEvent(void);
-
-public:
-
- // ==============================
- // Timer oriented public features
- // ==============================
-
- void init_ips(Bit32u ips);
- int register_timer( void *this_ptr, bx_timer_handler_t, Bit32u useconds,
- bx_bool continuous, bx_bool active, const char *id);
- unsigned unregisterTimer(int timerID);
- void start_timers(void);
- void activate_timer( unsigned timer_index, Bit32u useconds,
- bx_bool continuous );
- void deactivate_timer( unsigned timer_index );
- static BX_CPP_INLINE void tick1(void) {
-#if BX_SHOW_IPS
- {
- extern unsigned long ips_count;
- ips_count++;
- }
-#endif
- if (--bx_pc_system.currCountdown == 0) {
- bx_pc_system.countdownEvent();
- }
- }
- static BX_CPP_INLINE void tickn(Bit64u n) {
-#if BX_SHOW_IPS
- {
- extern unsigned long ips_count;
- ips_count += n;
- }
-#endif
- while (n >= Bit64u(bx_pc_system.currCountdown)) {
- n -= Bit64u(bx_pc_system.currCountdown);
- bx_pc_system.currCountdown = 0;
- bx_pc_system.countdownEvent();
- // bx_pc_system.currCountdown is adjusted to new value by countdownevent().
- };
- // 'n' is not (or no longer) >= the countdown size. We can just decrement
- // the remaining requested ticks and continue.
- bx_pc_system.currCountdown -= Bit32u(n);
- }
-
- int register_timer_ticks(void* this_ptr, bx_timer_handler_t, Bit64u ticks,
- bx_bool continuous, bx_bool active, const char *id);
- void activate_timer_ticks(unsigned index, Bit64u instructions,
- bx_bool continuous);
- Bit64u time_usec();
- Bit64u time_usec_sequential();
- static BX_CPP_INLINE Bit64u time_ticks() {
- return bx_pc_system.ticksTotal +
- Bit64u(bx_pc_system.currCountdownPeriod - bx_pc_system.currCountdown);
- }
- static BX_CPP_INLINE Bit64u getTicksTotal(void) {
- return bx_pc_system.ticksTotal;
- }
-
- static BX_CPP_INLINE Bit32u getNumCpuTicksLeftNextEvent(void) {
- return bx_pc_system.currCountdown;
- }
-#if BX_DEBUGGER
- static void timebp_handler(void* this_ptr);
-#endif
-
-
- // ===========================
- // Non-timer oriented features
- // ===========================
-
- bx_bool HRQ; // Hold Request
- //bx_bool INTR; // Interrupt
-
-
- // Address line 20 control:
- // 1 = enabled: extended memory is accessible
- // 0 = disabled: A20 address line is forced low to simulate
- // an 8088 address map
- bx_bool enable_a20;
-
- // start out masking physical memory addresses to:
- // 8086: 20 bits
- // 286: 24 bits
- // 386: 32 bits
- // when A20 line is disabled, mask physical memory addresses to:
- // 286: 20 bits
- // 386: 20 bits
- //
- Bit32u a20_mask;
-
- void set_HRQ(bx_bool val); // set the Hold ReQuest line
- void set_INTR(bx_bool value); // set the INTR line to value
-
- int IntEnabled( void );
- int InterruptSignal( PCS_OP operation );
- int ResetSignal( PCS_OP operation );
- Bit8u IAC(void);
-
- bx_pc_system_c(void);
-
- Bit32u inp(Bit16u addr, unsigned io_len) BX_CPP_AttrRegparmN(2);
- void outp(Bit16u addr, Bit32u value, unsigned io_len) BX_CPP_AttrRegparmN(3);
- void set_enable_a20(Bit8u value) BX_CPP_AttrRegparmN(1);
- bx_bool get_enable_a20(void);
- void exit(void);
-
- };
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: plugin.h,v 1.20 2003/08/04 16:03:08 akrisak Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// This file provides macros and types needed for plugins. It is based on
-// the plugin.h file from plex86, but with significant changes to make
-// it work in Bochs.
-// Plex86 is Copyright (C) 1999-2000 The plex86 developers team
-//
-/////////////////////////////////////////////////////////////////////////
-
-#ifndef __PLUGIN_H
-#define __PLUGIN_H
-
-#include "extplugin.h"
-
-class bx_devices_c;
-BOCHSAPI extern logfunctions *pluginlog;
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#define BX_PLUGIN_UNMAPPED "unmapped"
-#define BX_PLUGIN_BIOSDEV " biosdev"
-#define BX_PLUGIN_CMOS "cmos"
-#define BX_PLUGIN_VGA "vga"
-#define BX_PLUGIN_FLOPPY "floppy"
-#define BX_PLUGIN_PARALLEL "parallel"
-#define BX_PLUGIN_SERIAL "serial"
-#define BX_PLUGIN_KEYBOARD "keyboard"
-#define BX_PLUGIN_HARDDRV "harddrv"
-#define BX_PLUGIN_DMA "dma"
-#define BX_PLUGIN_PIC "pic"
-#define BX_PLUGIN_PCI "pci"
-#define BX_PLUGIN_PCI2ISA "pci2isa"
-#define BX_PLUGIN_SB16 "sb16"
-#define BX_PLUGIN_NE2K "ne2k"
-#define BX_PLUGIN_EXTFPUIRQ "extfpuirq"
-#define BX_PLUGIN_PCIVGA "pcivga"
-#define BX_PLUGIN_PCIUSB "pciusb"
-#define BX_PLUGIN_GAMEPORT "gameport"
-
-
-#define BX_REGISTER_DEVICE_DEVMODEL(a,b,c,d) pluginRegisterDeviceDevmodel(a,b,c,d)
-
-#if BX_PLUGINS
-
-#define DEV_init_devices() {bx_devices.init(BX_MEM(0)); }
-#define DEV_reset_devices(type) {bx_devices.reset(type); }
-#define PLUG_load_plugin(name,type) {bx_load_plugin(#name,type);}
-
-#define DEV_register_ioread_handler(b,c,d,e,f) pluginRegisterIOReadHandler(b,c,d,e,f)
-#define DEV_register_iowrite_handler(b,c,d,e,f) pluginRegisterIOWriteHandler(b,c,d,e,f)
-#define DEV_register_default_ioread_handler(b,c,d,e) pluginRegisterDefaultIOReadHandler(b,c,d,e)
-#define DEV_register_default_iowrite_handler(b,c,d,e) pluginRegisterDefaultIOWriteHandler(b,c,d,e)
-
-#define DEV_register_irq(b,c) pluginRegisterIRQ(b,c)
-#define DEV_unregister_irq(b,c) pluginUnregisterIRQ(b,c)
-
-#else
-
-#define DEV_init_devices() {bx_devices.init(BX_MEM(0)); }
-#define DEV_reset_devices(type) {bx_devices.reset(type); }
-// When plugins are off, PLUG_load_plugin will call the plugin_init function
-// directly.
-#define PLUG_load_plugin(name,type) {lib##name##_LTX_plugin_init(NULL,type,0,NULL);}
-#define DEV_register_ioread_handler(b,c,d,e,f) bx_devices.register_io_read_handler(b,c,d,e,f)
-#define DEV_register_iowrite_handler(b,c,d,e,f) bx_devices.register_io_write_handler(b,c,d,e,f)
-#define DEV_register_default_ioread_handler(b,c,d,e) bx_devices.register_default_io_read_handler(b,c,d,e)
-#define DEV_register_default_iowrite_handler(b,c,d,e) bx_devices.register_default_io_write_handler(b,c,d,e)
-#define DEV_register_irq(b,c) bx_devices.register_irq(b,c)
-#define DEV_unregister_irq(b,c) bx_devices.unregister_irq(b,c)
-
-#endif // #if BX_PLUGINS
-
-#define DEV_ioapic_present() (bx_devices.ioapic != NULL)
-
-// FIXME Do we really need pluginRegisterTimer ?
-#define DEV_register_timer(a,b,c,d,e,f) bx_pc_system.register_timer(a,b,c,d,e,f)
-
-///////// CMOS macros
-#define DEV_cmos_get_reg(a) (bx_devices.pluginCmosDevice->get_reg(a))
-#define DEV_cmos_set_reg(a,b) (bx_devices.pluginCmosDevice->set_reg(a,b))
-#define DEV_cmos_checksum() (bx_devices.pluginCmosDevice->checksum_cmos())
-#define DEV_cmos_get_timeval() (bx_devices.pluginCmosDevice->get_timeval())
-
-///////// keyboard macros
-#define DEV_mouse_motion(dx, dy, state) \
- (bx_devices.pluginKeyboard->mouse_motion(dx, dy, state))
-#define DEV_kbd_gen_scancode(key) \
- (bx_devices.pluginKeyboard->gen_scancode(key))
-#define DEV_kbd_paste_bytes(bytes, count) \
- (bx_devices.pluginKeyboard->paste_bytes(bytes,count))
-#define DEV_kbd_paste_delay_changed() \
- (bx_devices.pluginKeyboard->paste_delay_changed())
-#define DEV_mouse_enabled_changed(val) \
- (bx_devices.pluginKeyboard->mouse_enabled_changed(val))
-
-///////// hard drive macros
-#define DEV_hd_read_handler(a, b, c) \
- (bx_devices.pluginHardDrive->virt_read_handler(b, c))
-#define DEV_hd_write_handler(a, b, c, d) \
- (bx_devices.pluginHardDrive->virt_write_handler(b, c, d))
-#define DEV_hd_get_first_cd_handle() \
- (bx_devices.pluginHardDrive->get_first_cd_handle())
-#define DEV_hd_get_device_handle(a,b) \
- (bx_devices.pluginHardDrive->get_device_handle(a,b))
-#define DEV_hd_get_cd_media_status(handle) \
- (bx_devices.pluginHardDrive->get_cd_media_status(handle))
-#define DEV_hd_set_cd_media_status(handle, status) \
- (bx_devices.pluginHardDrive->set_cd_media_status(handle, status))
-#define DEV_hd_close_harddrive() bx_devices.pluginHardDrive->close_harddrive()
-#define DEV_hd_present() (bx_devices.pluginHardDrive != &bx_devices.stubHardDrive)
-
-#define DEV_bulk_io_quantum_requested() (bx_devices.bulkIOQuantumsRequested)
-#define DEV_bulk_io_quantum_transferred() (bx_devices.bulkIOQuantumsTransferred)
-#define DEV_bulk_io_host_addr() (bx_devices.bulkIOHostAddr)
-
-///////// FLOPPY macros
-#define DEV_floppy_get_media_status(drive) bx_devices.pluginFloppyDevice->get_media_status(drive)
-#define DEV_floppy_set_media_status(drive, status) bx_devices.pluginFloppyDevice->set_media_status(drive, status)
-#define DEV_floppy_present() (bx_devices.pluginFloppyDevice != &bx_devices.stubFloppy)
-
-///////// DMA macros
-#define DEV_dma_register_8bit_channel(channel, dmaRead, dmaWrite, name) \
- (bx_devices.pluginDmaDevice->registerDMA8Channel(channel, dmaRead, dmaWrite, name))
-#define DEV_dma_register_16bit_channel(channel, dmaRead, dmaWrite, name) \
- (bx_devices.pluginDmaDevice->registerDMA16Channel(channel, dmaRead, dmaWrite, name))
-#define DEV_dma_unregister_channel(channel) \
- (bx_devices.pluginDmaDevice->unregisterDMAChannel(channel))
-#define DEV_dma_set_drq(channel, val) \
- (bx_devices.pluginDmaDevice->set_DRQ(channel, val))
-#define DEV_dma_get_tc() \
- (bx_devices.pluginDmaDevice->get_TC())
-#define DEV_dma_raise_hlda() \
- (bx_devices.pluginDmaDevice->raise_HLDA())
-
-///////// PIC macros
-#define DEV_pic_lower_irq(b) (bx_devices.pluginPicDevice->lower_irq(b))
-#define DEV_pic_raise_irq(b) (bx_devices.pluginPicDevice->raise_irq(b))
-#define DEV_pic_iac() (bx_devices.pluginPicDevice->IAC())
-#define DEV_pic_show_pic_state() (bx_devices.pluginPicDevice->show_pic_state())
-
-///////// VGA macros
-#define DEV_vga_mem_read(addr) (bx_devices.pluginVgaDevice->mem_read(addr))
-#define DEV_vga_mem_write(addr, val) (bx_devices.pluginVgaDevice->mem_write(addr, val))
-#define DEV_vga_redraw_area(left, top, right, bottom) \
- (bx_devices.pluginVgaDevice->redraw_area(left, top, right, bottom))
-#define DEV_vga_get_text_snapshot(rawsnap, height, width) \
- (bx_devices.pluginVgaDevice->get_text_snapshot(rawsnap, height, width))
-#define DEV_vga_refresh() \
- (bx_devices.pluginVgaDevice->trigger_timer(bx_devices.pluginVgaDevice))
-#define DEV_vga_set_update_interval(val) \
- (bx_devices.pluginVgaDevice->set_update_interval(val))
-#define DEV_vga_get_actl_pal_idx(index) (bx_devices.pluginVgaDevice->get_actl_palette_idx(index))
-
-///////// PCI macros
-#define DEV_register_pci_handlers(b,c,d,e,f) \
- (bx_devices.pluginPciBridge->register_pci_handlers(b,c,d,e,f))
-#define DEV_pci_rd_memtype(addr) bx_devices.pluginPciBridge->rd_memType(addr)
-#define DEV_pci_wr_memtype(addr) bx_devices.pluginPciBridge->wr_memType(addr)
-#define DEV_pci_print_i440fx_state() bx_devices.pluginPciBridge->print_i440fx_state()
-
-///////// NE2000 macro
-#define DEV_ne2k_print_info(file,page,reg,brief) \
- bx_devices.pluginNE2kDevice->print_info(file,page,reg,brief)
-
-
-#if BX_HAVE_DLFCN_H
-#include <dlfcn.h>
-#endif
-
-typedef Bit32u (*ioReadHandler_t)(void *, Bit32u, unsigned);
-typedef void (*ioWriteHandler_t)(void *, Bit32u, Bit32u, unsigned);
-
-extern plugin_t *plugins;
-
-typedef struct _device_t
-{
- const char *name;
- plugin_t *plugin;
- void (*device_init_mem)(BX_MEM_C *);
- void (*device_init_dev)();
- void (*device_reset)(unsigned);
- void (*device_load_state)();
- void (*device_save_state)();
-
- int use_devmodel_interface; // BBD hack
- class bx_devmodel_c *devmodel; // BBD hack
-
- struct _device_t *next;
-} device_t;
-
-
-extern device_t *devices;
-
-void plugin_startup (void);
-void plugin_load (char *name, char *args, plugintype_t);
-plugin_t *plugin_unload (plugin_t *plugin);
-void plugin_init_all (void);
-void plugin_fini_all (void);
-
-/* === Device Stuff === */
-typedef void (*deviceInitMem_t)(BX_MEM_C *);
-typedef void (*deviceInitDev_t)(void);
-typedef void (*deviceReset_t)(unsigned);
-typedef void (*deviceLoad_t)(void);
-typedef void (*deviceSave_t)(void);
-
-BOCHSAPI void pluginRegisterDeviceDevmodel(plugin_t *plugin, plugintype_t type, bx_devmodel_c *dev, char *name);
-BOCHSAPI bx_bool pluginDevicePresent(char *name);
-
-/* === IO port stuff === */
-BOCHSAPI extern int (*pluginRegisterIOReadHandler)(void *thisPtr, ioReadHandler_t callback,
- unsigned base, const char *name, Bit8u mask);
-BOCHSAPI extern int (*pluginRegisterIOWriteHandler)(void *thisPtr, ioWriteHandler_t callback,
- unsigned base, const char *name, Bit8u mask);
-BOCHSAPI extern int (*pluginRegisterDefaultIOReadHandler)(void *thisPtr, ioReadHandler_t callback,
- const char *name, Bit8u mask);
-BOCHSAPI extern int (*pluginRegisterDefaultIOWriteHandler)(void *thisPtr, ioWriteHandler_t callback,
- const char *name, Bit8u mask);
-
-/* === A20 enable line stuff === */
-BOCHSAPI extern unsigned (*pluginGetA20E)(void);
-BOCHSAPI extern void (*pluginSetA20E)(unsigned val);
-
-/* === IRQ stuff === */
-BOCHSAPI extern void (*pluginRegisterIRQ)(unsigned irq, const char *name);
-BOCHSAPI extern void (*pluginUnregisterIRQ)(unsigned irq, const char *name);
-
-/* === Floppy stuff ===*/
-BOCHSAPI extern unsigned (* pluginFloppyGetMediaStatus)(unsigned drive);
-BOCHSAPI extern unsigned (* pluginFloppySetMediaStatus)(unsigned drive, unsigned status);
-
-/* === VGA stuff === */
-BOCHSAPI extern void (* pluginVGARedrawArea)(unsigned x0, unsigned y0,
- unsigned width, unsigned height);
-BOCHSAPI extern Bit8u (* pluginVGAMemRead)(Bit32u addr);
-BOCHSAPI extern void (* pluginVGAMemWrite)(Bit32u addr, Bit8u value);
-BOCHSAPI extern void (* pluginVGAGetTextSnapshot)(Bit8u **text_snapshot,
- unsigned *txHeight, unsigned *txWidth);
-BOCHSAPI extern void (* pluginVGARefresh)(void *);
-BOCHSAPI extern void (* pluginVGASetUpdateInterval)(unsigned);
-BOCHSAPI extern Bit8u (* pluginVGAGetActlPaletteIdx)(Bit8u index);
-
-/* === Timer stuff === */
-BOCHSAPI extern int (*pluginRegisterTimer)(void *this_ptr, void (*funct)(void *),
- Bit32u useconds, bx_bool continuous,
- bx_bool active, const char *name);
-
-BOCHSAPI extern void (*pluginActivateTimer)(unsigned id, Bit32u usec, bx_bool continuous);
-BOCHSAPI extern void (*pluginDeactivateTimer)(unsigned id);
-
-/* === HRQ stuff === */
-BOCHSAPI extern void (*pluginSetHRQ)(unsigned val);
-BOCHSAPI extern void (*pluginSetHRQHackCallback)( void (*callback)(void) );
-
-/* === Reset stuff === */
-BOCHSAPI extern void (*pluginResetSignal)(unsigned sig);
-
-/* === PCI stuff === */
-BOCHSAPI extern bx_bool (*pluginRegisterPCIDevice)(void *this_ptr,
- Bit32u (*bx_pci_read_handler)(void *, Bit8u, unsigned),
- void(*bx_pci_write_handler)(void *, Bit8u, Bit32u, unsigned),
- Bit8u devfunc, const char *name);
-BOCHSAPI extern Bit8u (*pluginRd_memType)(Bit32u addr);
-BOCHSAPI extern Bit8u (*pluginWr_memType)(Bit32u addr);
-
-void plugin_abort (void);
-
-int bx_load_plugin (const char *name, plugintype_t type);
-extern void bx_init_plugins (void);
-extern void bx_reset_plugins (unsigned);
-
-// every plugin must define these, within the extern"C" block, so that
-// a non-mangled function symbol is available in the shared library.
-void plugin_fini(void);
-int plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]);
-
-// still in extern "C"
-#define DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(mod) \
- int lib##mod##_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[]); \
- void lib##mod##_LTX_plugin_fini(void);
-
-DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(harddrv)
-DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(keyboard)
-DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(serial)
-DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(unmapped)
-DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(biosdev)
-DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(cmos)
-DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(dma)
-DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(pic)
-DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(vga)
-DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(floppy)
-DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(parallel)
-DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(pci)
-DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(pci2isa)
-DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(pcivga)
-DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(pciusb)
-DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(sb16)
-DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(ne2k)
-DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(extfpuirq)
-DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(gameport)
-DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(amigaos)
-DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(beos)
-DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(carbon)
-DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(macintosh)
-DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(nogui)
-DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(rfb)
-DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(sdl)
-DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(svga)
-DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(term)
-DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(win32)
-DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(wx)
-DECLARE_PLUGIN_INIT_FINI_FOR_MODULE(x)
-
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __PLUGIN_H */
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: state_file.h,v 1.5 2002/10/24 21:05:00 bdenney Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2001 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-// Classes for helping to make checkpoints of the emulator state.
-
-#ifndef _STATE_FILE_H
-#define _STATE_FILE_H
-#include <stdio.h>
-#include <stddef.h>
-
-
-class BOCHSAPI state_file {
- void init(void);
-public:
- FILE *file;
- class logfunctions *log;
-
- FILE *get_handle();
- void write(Bit8u);
- void write(Bit16u);
- void write(Bit32u);
- void write(Bit64u);
- void write(const void*, size_t);
- void read(Bit8u &);
- void read(Bit16u &);
- void read(Bit32u &);
- void read(Bit64u &);
- void read(void *, size_t);
- void write_check(const char *);
- void read_check (const char *);
-
- state_file (const char *name, const char *options);
- state_file (FILE *f);
- ~state_file();
-};
-
-#endif // #ifndef _STATE_FILE_H
+++ /dev/null
-XEN_ROOT= ../../../
-include $(XEN_ROOT)/tools/Rules.mk
-
-TOPDIR= ..
-CXXFLAGS=-I. -I../include -I..
-
-ifeq ($(XEN_TARGET_ARCH), x86_32)
-CXXFLAGS+=-D_FILE_OFFSET_BITS=64
-endif
-
-OBJS=$(patsubst %.cc,%.o,$(wildcard *.cc))
-BXLIBS = ../gui/libgui.a ../memory/libmemory.a
-LDLIBS= $(BXLIBS) $(X11_LDPATH) -lX11 -lXpm -lstdc++ -L../../../tools/libxc -L../../../tools/libxutil -lxc -lxutil -lpthread -lncurses
-
-all: device-model
-
-device-model: $(OBJS) $(BXLIBS)
- $(CC) $(LDFLAGS) $(OBJS) $(LOADLIBES) $(LDLIBS) -o $@
-
-include $(TOPDIR)/mk/helix.mk
-
-install:: all
- install device-model $(DESTDIR)/usr/sbin
+++ /dev/null
-//
-// iodev/aspi-win32.h
-// $Id: aspi-win32.h,v 1.2 2001/06/25 12:52:37 bdenney Exp $
-//
-// This file was copied from cdrecord 1.9 under libscg/scg/aspi-win32.h.
-// The only modification is related to use of the PACKED keyword.
-//
-
-#ifndef __ASPI_WIN32_H_
-#define __ASPI_WIN32_H_
-
-#include <windows.h>
-
-#ifndef PACKED
-// It seems that VC++ has no PACKED keyword but Cygwin does. We can just
-// define PACKED to be empty if it's not already defined by the system
-// headers.
-#define PACKED /* empty */
-#endif
-
-/***************************************************************************
- ** SCSI MISCELLANEOUS EQUATES
- ***************************************************************************/
-#define SENSE_LEN 14 /* Default sense buffer length */
-#define SRB_DIR_SCSI 0x00 /* Direction determined by SCSI */
-#define SRB_POSTING 0x01 /* Enable ASPI posting */
-#define SRB_ENABLE_RESIDUAL_COUNT 0x04 /* Enable residual byte count */
- /* reporting */
-#define SRB_DIR_IN 0x08 /* Transfer from SCSI target to */
- /* host */
-#define SRB_DIR_OUT 0x10 /* Transfer from host to SCSI */
- /* target */
-#define SRB_EVENT_NOTIFY 0x40 /* Enable ASPI event notification */
-#define RESIDUAL_COUNT_SUPPORTED 0x02 /* Extended buffer flag */
-#define MAX_SRB_TIMEOUT 1080001u /* 30 hour maximum timeout in sec */
-#define DEFAULT_SRB_TIMEOUT 1080001u /* use max.timeout by default */
-
-/***************************************************************************
- ** ASPI command definitions
- ***************************************************************************/
-#define SC_HA_INQUIRY 0x00 /* Host adapter inquiry */
-#define SC_GET_DEV_TYPE 0x01 /* Get device type */
-#define SC_EXEC_SCSI_CMD 0x02 /* Execute SCSI command */
-#define SC_ABORT_SRB 0x03 /* Abort an SRB */
-#define SC_RESET_DEV 0x04 /* SCSI bus device reset */
-#define SC_SET_HA_PARMS 0x05 /* Set HA parameters */
-#define SC_GET_DISK_INFO 0x06 /* Get Disk */
-#define SC_RESCAN_SCSI_BUS 0x07 /* Rebuild SCSI device map */
-#define SC_GETSET_TIMEOUTS 0x08 /* Get/Set target timeouts */
-
-
-/***************************************************************************
- ** SRB Status
- ***************************************************************************/
-#define SS_PENDING 0x00 /* SRB being processed */
-#define SS_COMP 0x01 /* SRB completed without error */
-#define SS_ABORTED 0x02 /* SRB aborted */
-#define SS_ABORT_FAIL 0x03 /* Unable to abort SRB */
-#define SS_ERR 0x04 /* SRB completed with error */
-#define SS_INVALID_CMD 0x80 /* Invalid ASPI command */
-#define SS_INVALID_HA 0x81 /* Invalid host adapter number */
-#define SS_NO_DEVICE 0x82 /* SCSI device not installed */
-#define SS_INVALID_SRB 0xE0 /* Invalid parameter set in SRB */
-#define SS_OLD_MANAGER 0xE1 /* ASPI manager doesn't support */
- /* windows */
-#define SS_BUFFER_ALIGN 0xE1 /* Buffer not aligned (replaces */
- /* SS_OLD_MANAGER in Win32) */
-#define SS_ILLEGAL_MODE 0xE2 /* Unsupported Windows mode */
-#define SS_NO_ASPI 0xE3 /* No ASPI managers */
-#define SS_FAILED_INIT 0xE4 /* ASPI for windows failed init */
-#define SS_ASPI_IS_BUSY 0xE5 /* No resources available to */
- /* execute command */
-#define SS_BUFFER_TO_BIG 0xE6 /* Buffer size too big to handle */
-#define SS_BUFFER_TOO_BIG 0xE6 /* Correct spelling of 'too' */
-#define SS_MISMATCHED_COMPONENTS 0xE7 /* The DLLs/EXEs of ASPI don't */
- /* version check */
-#define SS_NO_ADAPTERS 0xE8 /* No host adapters to manager */
-#define SS_INSUFFICIENT_RESOURCES 0xE9 /* Couldn't allocate resources */
- /* needed to init */
-#define SS_ASPI_IS_SHUTDOWN 0xEA /* Call came to ASPI after */
- /* PROCESS_DETACH */
-#define SS_BAD_INSTALL 0xEB /* The DLL or other components */
- /* are installed wrong */
-
-/***************************************************************************
- ** Host Adapter Status
- ***************************************************************************/
-#define HASTAT_OK 0x00 /* No error detected by HA */
-#define HASTAT_SEL_TO 0x11 /* Selection Timeout */
-#define HASTAT_DO_DU 0x12 /* Data overrun/data underrun */
-#define HASTAT_BUS_FREE 0x13 /* Unexpected bus free */
-#define HASTAT_PHASE_ERR 0x14 /* Target bus phase sequence */
-#define HASTAT_TIMEOUT 0x09 /* Timed out while SRB was */
- /* waiting to be processed */
-#define HASTAT_COMMAND_TIMEOUT 0x0B /* Adapter timed out while */
- /* processing SRB */
-#define HASTAT_MESSAGE_REJECT 0x0D /* While processing the SRB, the */
- /* adapter received a MESSAGE */
-#define HASTAT_BUS_RESET 0x0E /* A bus reset was detected */
-#define HASTAT_PARITY_ERROR 0x0F /* A parity error was detected */
-#define HASTAT_REQUEST_SENSE_FAILED 0x10 /* The adapter failed in issuing */
-
-/***************************************************************************
- ** SRB - HOST ADAPTER INQUIRIY - SC_HA_INQUIRY (0)
- ***************************************************************************/
-typedef struct {
- BYTE SRB_Cmd; /* 00/000 ASPI command code == SC_HA_INQUIRY */
- BYTE SRB_Status; /* 01/001 ASPI command status byte */
- BYTE SRB_HaId; /* 02/002 ASPI host adapter number */
- BYTE SRB_Flags; /* 03/003 ASPI request flags */
- DWORD SRB_Hdr_Rsvd; /* 04/004 Reserved, must = 0 */
- BYTE HA_Count; /* 08/008 Number of host adapters present */
- BYTE HA_SCSI_ID; /* 09/009 SCSI ID of host adapter */
- BYTE HA_ManagerId[16]; /* 0a/010 String describing the manager */
- BYTE HA_Identifier[16]; /* 1a/026 String describing the host adapter */
- BYTE HA_Unique[16]; /* 2a/042 Host Adapter Unique parameters */
- WORD HA_Rsvd1; /* 3a/058 Reserved, must = 0 */
-} PACKED SRB_HAInquiry, *PSRB_HAInquiry, FAR *LPSRB_HAInquiry;
-
-
-/***************************************************************************
- ** SRB - GET DEVICE TYPE - SC_GET_DEV_TYPE (1)
- ***************************************************************************/
-typedef struct
-{
- BYTE SRB_Cmd; /* 00/000 ASPI cmd code == SC_GET_DEV_TYPE */
- BYTE SRB_Status; /* 01/001 ASPI command status byte */
- BYTE SRB_HaId; /* 02/002 ASPI host adapter number */
- BYTE SRB_Flags; /* 03/003 Reserved, must = 0 */
- DWORD SRB_Hdr_Rsvd; /* 04/004 Reserved, must = 0 */
- BYTE SRB_Target; /* 08/008 Target's SCSI ID */
- BYTE SRB_Lun; /* 09/009 Target's LUN number */
- BYTE SRB_DeviceType; /* 0a/010 Target's peripheral device type */
- BYTE SRB_Rsvd1; /* 0b/011 Reserved, must = 0 */
-} PACKED SRB_GDEVBlock, *PSRB_GDEVBlock, FAR *LPSRB_GDEVBlock;
-
-
-/***************************************************************************
- ** SRB - EXECUTE SCSI COMMAND - SC_EXEC_SCSI_CMD (2)
- ***************************************************************************/
-typedef struct
-{
- BYTE SRB_Cmd; /* 00/000 ASPI cmd code == SC_EXEC_SCSI_CMD */
- BYTE SRB_Status; /* 01/001 ASPI command status byte */
- BYTE SRB_HaId; /* 02/002 ASPI host adapter number */
- BYTE SRB_Flags; /* 03/003 Reserved, must = 0 */
- DWORD SRB_Hdr_Rsvd; /* 04/004 Reserved, must = 0 */
- BYTE SRB_Target; /* 08/008 Target's SCSI ID */
- BYTE SRB_Lun; /* 09/009 Target's LUN */
- WORD SRB_Rsvd1; /* 0a/010 Reserved for alignment */
- DWORD SRB_BufLen; /* 0c/012 Data Allocation Length */
- BYTE FAR *SRB_BufPointer; /* 10/016 Data Buffer Pointer */
- BYTE SRB_SenseLen; /* 14/020 Sense Allocation Length */
- BYTE SRB_CDBLen; /* 15/021 CDB Length */
- BYTE SRB_HaStat; /* 16/022 Host Adapter Status */
- BYTE SRB_TargStat; /* 17/023 Target Status */
- VOID FAR *SRB_PostProc; /* 18/024 Post routine */
- BYTE SRB_Rsvd2[20]; /* 1c/028 Reserved, must = 0 */
- BYTE CDBByte[16]; /* 30/048 SCSI CDB */
- BYTE SenseArea[SENSE_LEN+2]; /* 40/064 Request Sense buffer */
-} PACKED SRB_ExecSCSICmd, *PSRB_ExecSCSICmd, FAR *LPSRB_ExecSCSICmd;
-
-
-typedef struct
-{
- BYTE SRB_Cmd; /* 00/000 ASPI cmd code == SC_ABORT_SRB */
- BYTE SRB_Status; /* 01/001 ASPI command status byte */
- BYTE SRB_HaId; /* 02/002 ASPI host adapter number */
- BYTE SRB_Flags; /* 03/003 Reserved, must = 0 */
- DWORD SRB_Hdr_Rsvd; /* 04/004 Reserved, must = 0 */
- void *SRB_ToAbort; /* 08/008 Pointer to SRB to abort */
-} PACKED SRB_Abort, *PSRB_Abort, FAR *LPSRB_Abort;
-
-
-/***************************************************************************
- ** SRB - BUS DEVICE RESET - SC_RESET_DEV (4)
- ***************************************************************************/
-typedef struct
-{
- BYTE SRB_Cmd; /* 00/000 ASPI cmd code == SC_RESET_DEV */
- BYTE SRB_Status; /* 01/001 ASPI command status byte */
- BYTE SRB_HaId; /* 02/002 ASPI host adapter number */
- DWORD SRB_Flags; /* 04/004 Reserved */
- BYTE SRB_Target; /* 08/008 Target's SCSI ID */
- BYTE SRB_Lun; /* 09/009 Target's LUN number */
- BYTE SRB_Rsvd1[12]; /* 0A/010 Reserved for alignment */
- BYTE SRB_HaStat; /* 16/022 Host Adapter Status */
- BYTE SRB_TargStat; /* 17/023 Target Status */
- VOID FAR *SRB_PostProc; /* 18/024 Post routine */
- BYTE SRB_Rsvd2[36]; /* 1C/028 Reserved, must = 0 */
-} SRB_BusDeviceReset, *PSRB_BusDeviceReset, FAR *LPSRB_BusDeviceReset;
-
-typedef struct tag_ASPI32BUFF
-{
- PBYTE AB_BufPointer;
- DWORD AB_BufLen;
- DWORD AB_ZeroFill;
- DWORD AB_Reserved;
-} PACKED ASPI32BUFF, *PASPI32BUFF, FAR *LPASPI32BUFF;
-
-typedef struct
-{
- BYTE SRB_Cmd;
- BYTE SRB_Status;
- BYTE SRB_HaId;
- BYTE SRB_Flags;
- DWORD SRB_Hdr_Rsvd;
-} SRB, *PSRB, FAR *LPSRB;
-
-#endif
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: biosdev.cc,v 1.7 2003/12/08 19:36:23 danielg4 Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-// Here are the virtual ports use to display messages from the bioses :
-//
-// 0x0400 : rombios Panic port with message
-// 0x0401 : rombios Panic port with line number
-// 0x0402 : rombios Info port with message
-// 0x0403 : rombios Debug port with message
-//
-// 0x0500 : vgabios Info port with message
-// 0x0501 : vgabios Panic port with message
-// 0x0502 : vgabios Panic port with line number
-// 0x0503 : vgabios Debug port with message
-
-
-// Define BX_PLUGGABLE in files that can be compiled into plugins. For
-// platforms that require a special tag on exported symbols, BX_PLUGGABLE
-// is used to know when we are exporting symbols and when we are importing.
-#define BX_PLUGGABLE
-
-#include "bochs.h"
-
-bx_biosdev_c *theBiosDevice;
-
- int
-libbiosdev_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[])
-{
- theBiosDevice = new bx_biosdev_c ();
- bx_devices.pluginBiosDevice = theBiosDevice;
- BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theBiosDevice, BX_PLUGIN_BIOSDEV);
- return(0); // Success
-}
-
- void
-libbiosdev_LTX_plugin_fini(void)
-{
-}
-
-logfunctions *bioslog;
-logfunctions *vgabioslog;
-
-bx_biosdev_c::bx_biosdev_c(void)
-{
- bioslog = new logfunctions();
- bioslog->put("BIOS");
- bioslog->settype(BIOSLOG);
- s.bios_message_i = 0;
-
- vgabioslog = new logfunctions();
- vgabioslog->put("VBIOS");
- vgabioslog->settype(BIOSLOG);
- s.vgabios_message_i = 0;
-}
-
-bx_biosdev_c::~bx_biosdev_c(void)
-{
- if ( bioslog != NULL )
- {
- delete bioslog;
- bioslog = NULL;
- }
-
- if ( vgabioslog != NULL )
- {
- delete vgabioslog;
- vgabioslog = NULL;
- }
-}
-
- void
-bx_biosdev_c::init(void)
-{
- DEV_register_iowrite_handler(this, write_handler, 0x0400, "Bios Panic Port 1", 3);
- DEV_register_iowrite_handler(this, write_handler, 0x0401, "Bios Panic Port 2", 3);
- DEV_register_iowrite_handler(this, write_handler, 0x0403, "Bios Debug Port", 1);
- DEV_register_iowrite_handler(this, write_handler, 0x0402, "Bios Info Port", 1);
-
- DEV_register_iowrite_handler(this, write_handler, 0x0501, "VGABios Panic Port 1", 3);
- DEV_register_iowrite_handler(this, write_handler, 0x0502, "VGABios Panic Port 2", 3);
- DEV_register_iowrite_handler(this, write_handler, 0x0503, "VGABios Debug Port", 1);
- DEV_register_iowrite_handler(this, write_handler, 0x0500, "VGABios Info Port", 1);
-}
-
- void
-bx_biosdev_c::reset(unsigned type)
-{
-}
-
- // static IO port write callback handler
- // redirects to non-static class handler to avoid virtual functions
-
- void
-bx_biosdev_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len)
-{
-#if !BX_USE_BIOS_SMF
- bx_biosdev_c *class_ptr = (bx_biosdev_c *) this_ptr;
-
- class_ptr->write(address, value, io_len);
-}
-
- void
-bx_biosdev_c::write(Bit32u address, Bit32u value, unsigned io_len)
-{
-#else
- UNUSED(this_ptr);
-#endif // !BX_USE_BIOS_SMF
- UNUSED(io_len);
-
-
- switch (address) {
- // 0x400-0x401 are used as panic ports for the rombios
- case 0x0401:
- if (BX_BIOS_THIS s.bios_message_i > 0) {
- // if there are bits of message in the buffer, print them as the
- // panic message. Otherwise fall into the next case.
- if (BX_BIOS_THIS s.bios_message_i >= BX_BIOS_MESSAGE_SIZE)
- BX_BIOS_THIS s.bios_message_i = BX_BIOS_MESSAGE_SIZE-1;
- BX_BIOS_THIS s.bios_message[ BX_BIOS_THIS s.bios_message_i] = 0;
- BX_BIOS_THIS s.bios_message_i = 0;
- bioslog->panic("%s", BX_BIOS_THIS s.bios_message);
- break;
- }
- case 0x0400:
- bioslog->panic("BIOS panic at rombios.c, line %d", value);
- break;
-
- // 0x0402 is used as the info port for the rombios
- // 0x0403 is used as the debug port for the rombios
- case 0x0402:
- case 0x0403:
- BX_BIOS_THIS s.bios_message[BX_BIOS_THIS s.bios_message_i] =
- (Bit8u) value;
- BX_BIOS_THIS s.bios_message_i ++;
- if ( BX_BIOS_THIS s.bios_message_i >= BX_BIOS_MESSAGE_SIZE ) {
- BX_BIOS_THIS s.bios_message[ BX_BIOS_MESSAGE_SIZE - 1] = 0;
- BX_BIOS_THIS s.bios_message_i = 0;
- if (address==0x403) bioslog->ldebug("%s", BX_BIOS_THIS s.bios_message);
- else bioslog->info("%s", BX_BIOS_THIS s.bios_message);
- }
- else if ((value & 0xff) == '\n') {
- BX_BIOS_THIS s.bios_message[ BX_BIOS_THIS s.bios_message_i - 1 ] = 0;
- BX_BIOS_THIS s.bios_message_i = 0;
- if (address==0x403) bioslog->ldebug("%s", BX_BIOS_THIS s.bios_message);
- else bioslog->info("%s", BX_BIOS_THIS s.bios_message);
- }
- break;
-
- // 0x501-0x502 are used as panic ports for the vgabios
- case 0x0502:
- if (BX_BIOS_THIS s.vgabios_message_i > 0) {
- // if there are bits of message in the buffer, print them as the
- // panic message. Otherwise fall into the next case.
- if (BX_BIOS_THIS s.vgabios_message_i >= BX_BIOS_MESSAGE_SIZE)
- BX_BIOS_THIS s.vgabios_message_i = BX_BIOS_MESSAGE_SIZE-1;
- BX_BIOS_THIS s.vgabios_message[ BX_BIOS_THIS s.vgabios_message_i] = 0;
- BX_BIOS_THIS s.vgabios_message_i = 0;
- vgabioslog->panic("%s", BX_BIOS_THIS s.vgabios_message);
- break;
- }
- case 0x0501:
- vgabioslog->panic("BIOS panic at rombios.c, line %d", value);
- break;
-
- // 0x0500 is used as the message port for the vgabios
- case 0x0500:
- case 0x0503:
- BX_BIOS_THIS s.vgabios_message[BX_BIOS_THIS s.vgabios_message_i] =
- (Bit8u) value;
- BX_BIOS_THIS s.vgabios_message_i ++;
- if ( BX_BIOS_THIS s.vgabios_message_i >= BX_BIOS_MESSAGE_SIZE ) {
- BX_BIOS_THIS s.vgabios_message[ BX_BIOS_MESSAGE_SIZE - 1] = 0;
- BX_BIOS_THIS s.vgabios_message_i = 0;
- if (address==0x503) vgabioslog->ldebug("%s", BX_BIOS_THIS s.vgabios_message);
- else vgabioslog->info("%s", BX_BIOS_THIS s.vgabios_message);
- }
- else if ((value & 0xff) == '\n') {
- BX_BIOS_THIS s.vgabios_message[ BX_BIOS_THIS s.vgabios_message_i - 1 ] = 0;
- BX_BIOS_THIS s.vgabios_message_i = 0;
- if (address==0x503) vgabioslog->ldebug("%s", BX_BIOS_THIS s.vgabios_message);
- else vgabioslog->info("%s", BX_BIOS_THIS s.vgabios_message);
- }
- break;
-
- default:
- break;
- }
-}
+++ /dev/null
-
-// $Id: biosdev.h,v 1.3 2002/10/24 21:07:09 bdenney Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-#define BX_BIOS_MESSAGE_SIZE 80
-
-
-#if BX_USE_BIOS_SMF
-# define BX_BIOS_SMF static
-# define BX_BIOS_THIS theBiosDevice->
-#else
-# define BX_BIOS_SMF
-# define BX_BIOS_THIS this->
-#endif
-
-
-class bx_biosdev_c : public bx_devmodel_c {
-public:
- bx_biosdev_c(void);
- ~bx_biosdev_c(void);
-
- virtual void init(void);
- virtual void reset (unsigned type);
-
-private:
-
- static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len);
-#if !BX_USE_BIOS_SMF
- void write(Bit32u address, Bit32u value, unsigned io_len);
-#endif
-
- struct {
- Bit8u bios_message[BX_BIOS_MESSAGE_SIZE];
- unsigned int bios_message_i;
-
- Bit8u vgabios_message[BX_BIOS_MESSAGE_SIZE];
- unsigned int vgabios_message_i;
- } s; // state information
-
- };
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: cdrom.cc,v 1.66 2003/12/08 23:49:48 danielg4 Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-// These are the low-level CDROM functions which are called
-// from 'harddrv.cc'. They effect the OS specific functionality
-// needed by the CDROM emulation in 'harddrv.cc'. Mostly, just
-// ioctl() calls and such. Should be fairly easy to add support
-// for your OS if it is not supported yet.
-
-
-// Define BX_PLUGGABLE in files that can be compiled into plugins. For
-// platforms that require a special tag on exported symbols, BX_PLUGGABLE
-// is used to know when we are exporting symbols and when we are importing.
-#define BX_PLUGGABLE
-
-#include "bochs.h"
-#if BX_SUPPORT_CDROM
-
-#define LOG_THIS /* no SMF tricks here, not needed */
-
-extern "C" {
-#include <errno.h>
-}
-
-#ifdef __linux__
-extern "C" {
-#include <sys/ioctl.h>
-#include <linux/cdrom.h>
-// I use the framesize in non OS specific code too
-#define BX_CD_FRAMESIZE CD_FRAMESIZE
-}
-
-#elif defined(__GNU__) || (defined(__CYGWIN32__) && !defined(WIN32))
-extern "C" {
-#include <sys/ioctl.h>
-#define BX_CD_FRAMESIZE 2048
-#define CD_FRAMESIZE 2048
-}
-
-#elif BX_WITH_MACOS
-#define BX_CD_FRAMESIZE 2048
-#define CD_FRAMESIZE 2048
-
-#elif defined(__sun)
-extern "C" {
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <sys/cdio.h>
-#define BX_CD_FRAMESIZE CDROM_BLK_2048
-}
-
-#elif defined(__DJGPP__)
-extern "C" {
-#include <sys/ioctl.h>
-#define BX_CD_FRAMESIZE 2048
-#define CD_FRAMESIZE 2048
-}
-
-#elif defined(__BEOS__)
-#include "cdrom_beos.h"
-#define BX_CD_FRAMESIZE 2048
-
-#elif (defined (__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__))
-// OpenBSD pre version 2.7 may require extern "C" { } structure around
-// all the includes, because the i386 sys/disklabel.h contains code which
-// c++ considers invalid.
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/file.h>
-#include <sys/cdio.h>
-#include <sys/ioctl.h>
-#include <sys/disklabel.h>
-// ntohl(x) et al have been moved out of sys/param.h in FreeBSD 5
-#include <netinet/in.h>
-
-// XXX
-#define BX_CD_FRAMESIZE 2048
-#define CD_FRAMESIZE 2048
-
-#elif defined(__APPLE__)
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <dev/disk.h>
-#include <errno.h>
-#include <paths.h>
-#include <sys/param.h>
-
-#include <IOKit/IOKitLib.h>
-#include <IOKit/IOBSD.h>
-#include <IOKit/storage/IOCDMedia.h>
-#include <IOKit/storage/IOMedia.h>
-#include <IOKit/storage/IOCDTypes.h>
-#include <CoreFoundation/CoreFoundation.h>
-
-// These definitions were taken from mount_cd9660.c
-// There are some similar definitions in IOCDTypes.h
-// however there seems to be some dissagreement in
-// the definition of CDTOC.length
-struct _CDMSF {
- u_char minute;
- u_char second;
- u_char frame;
-};
-
-#define MSF_TO_LBA(msf) \
- (((((msf).minute * 60UL) + (msf).second) * 75UL) + (msf).frame - 150)
-
-struct _CDTOC_Desc {
- u_char session;
- u_char ctrl_adr; /* typed to be machine and compiler independent */
- u_char tno;
- u_char point;
- struct _CDMSF address;
- u_char zero;
- struct _CDMSF p;
-};
-
-struct _CDTOC {
- u_short length; /* in native cpu endian */
- u_char first_session;
- u_char last_session;
- struct _CDTOC_Desc trackdesc[1];
-};
-
-static kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator, mach_port_t *masterPort );
-static kern_return_t GetDeviceFilePath( io_iterator_t mediaIterator, char *deviceFilePath, CFIndex maxPathSize );
-//int OpenDrive( const char *deviceFilePath );
-static struct _CDTOC * ReadTOC( const char * devpath );
-
-static char CDDevicePath[ MAXPATHLEN ];
-
-#define BX_CD_FRAMESIZE 2048
-#define CD_FRAMESIZE 2048
-
-#elif defined(WIN32)
-// windows.h included by bochs.h
-#include <winioctl.h>
-#include "aspi-win32.h"
-#include "scsidefs.h"
-
-DWORD (*GetASPI32SupportInfo)(void);
-DWORD (*SendASPI32Command)(LPSRB);
-BOOL (*GetASPI32Buffer)(PASPI32BUFF);
-BOOL (*FreeASPI32Buffer)(PASPI32BUFF);
-BOOL (*TranslateASPI32Address)(PDWORD,PDWORD);
-DWORD (*GetASPI32DLLVersion)(void);
-
-
-static BOOL bUseASPI = FALSE;
-static BOOL bHaveDev;
-static UINT cdromCount = 0;
-static HINSTANCE hASPI = NULL;
-
-#define BX_CD_FRAMESIZE 2048
-#define CD_FRAMESIZE 2048
-
-#else // all others (Irix, Tru64)
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#define BX_CD_FRAMESIZE 2048
-#define CD_FRAMESIZE 2048
-#endif
-
-#include <stdio.h>
-
-#ifdef __APPLE__
-static kern_return_t FindEjectableCDMedia( io_iterator_t *mediaIterator,
- mach_port_t *masterPort )
-{
- kern_return_t kernResult;
- CFMutableDictionaryRef classesToMatch;
- kernResult = IOMasterPort( bootstrap_port, masterPort );
- if ( kernResult != KERN_SUCCESS )
- {
- fprintf ( stderr, "IOMasterPort returned %d\n", kernResult );
- return kernResult;
- }
- // CD media are instances of class kIOCDMediaClass.
- classesToMatch = IOServiceMatching( kIOCDMediaClass );
- if ( classesToMatch == NULL )
- fprintf ( stderr, "IOServiceMatching returned a NULL dictionary.\n" );
- else
- {
- // Each IOMedia object has a property with key kIOMediaEjectableKey
- // which is true if the media is indeed ejectable. So add property
- // to CFDictionary for matching.
- CFDictionarySetValue( classesToMatch,
- CFSTR( kIOMediaEjectableKey ), kCFBooleanTrue );
- }
- kernResult = IOServiceGetMatchingServices( *masterPort,
- classesToMatch, mediaIterator );
- if ( (kernResult != KERN_SUCCESS) || (*mediaIterator == NULL) )
- fprintf( stderr, "No ejectable CD media found.\n kernResult = %d\n", kernResult );
-
- return kernResult;
-}
-
-
-static kern_return_t GetDeviceFilePath( io_iterator_t mediaIterator,
- char *deviceFilePath, CFIndex maxPathSize )
-{
- io_object_t nextMedia;
- kern_return_t kernResult = KERN_FAILURE;
- nextMedia = IOIteratorNext( mediaIterator );
- if ( nextMedia == NULL )
- {
- *deviceFilePath = '\0';
- }
- else
- {
- CFTypeRef deviceFilePathAsCFString;
- deviceFilePathAsCFString = IORegistryEntryCreateCFProperty(
- nextMedia, CFSTR( kIOBSDNameKey ),
- kCFAllocatorDefault, 0 );
- *deviceFilePath = '\0';
- if ( deviceFilePathAsCFString )
- {
- size_t devPathLength = strlen( _PATH_DEV );
- strcpy( deviceFilePath, _PATH_DEV );
- if ( CFStringGetCString( (const __CFString *) deviceFilePathAsCFString,
- deviceFilePath + devPathLength,
- maxPathSize - devPathLength,
- kCFStringEncodingASCII ) )
- {
- // fprintf( stderr, "BSD path: %s\n", deviceFilePath );
- kernResult = KERN_SUCCESS;
- }
- CFRelease( deviceFilePathAsCFString );
- }
- }
- IOObjectRelease( nextMedia );
- return kernResult;
-}
-
-
-static int OpenDrive( const char *deviceFilePath )
-{
-
- int fileDescriptor;
-
- fileDescriptor = open( deviceFilePath, O_RDONLY );
- if ( fileDescriptor == -1 )
- fprintf( stderr, "Error %d opening device %s.\n", errno, deviceFilePath );
- return fileDescriptor;
-
-}
-
-static struct _CDTOC * ReadTOC( const char * devpath ) {
-
- struct _CDTOC * toc_p = NULL;
- io_iterator_t iterator = 0;
- io_registry_entry_t service = 0;
- CFDictionaryRef properties = 0;
- CFDataRef data = 0;
- mach_port_t port = 0;
- char * devname;
-
- if (( devname = strrchr( devpath, '/' )) != NULL ) {
- ++devname;
- }
- else {
- devname = (char *) devpath;
- }
-
- if ( IOMasterPort(bootstrap_port, &port ) != KERN_SUCCESS ) {
- fprintf( stderr, "IOMasterPort failed\n" );
- goto Exit;
- }
-
- if ( IOServiceGetMatchingServices( port, IOBSDNameMatching( port, 0, devname ),
- &iterator ) != KERN_SUCCESS ) {
- fprintf( stderr, "IOServiceGetMatchingServices failed\n" );
- goto Exit;
- }
-
- service = IOIteratorNext( iterator );
-
- IOObjectRelease( iterator );
-
- iterator = 0;
-
- while ( service && !IOObjectConformsTo( service, "IOCDMedia" )) {
- if ( IORegistryEntryGetParentIterator( service, kIOServicePlane,
- &iterator ) != KERN_SUCCESS ) {
- fprintf( stderr, "IORegistryEntryGetParentIterator failed\n" );
- goto Exit;
- }
-
- IOObjectRelease( service );
- service = IOIteratorNext( iterator );
- IOObjectRelease( iterator );
-
- }
-
- if ( service == NULL ) {
- fprintf( stderr, "CD media not found\n" );
- goto Exit;
- }
-
- if ( IORegistryEntryCreateCFProperties( service, (__CFDictionary **) &properties,
- kCFAllocatorDefault,
- kNilOptions ) != KERN_SUCCESS ) {
- fprintf( stderr, "IORegistryEntryGetParentIterator failed\n" );
- goto Exit;
- }
-
- data = (CFDataRef) CFDictionaryGetValue( properties, CFSTR(kIOCDMediaTOCKey) );
- if ( data == NULL ) {
- fprintf( stderr, "CFDictionaryGetValue failed\n" );
- goto Exit;
- }
- else {
-
- CFRange range;
- CFIndex buflen;
-
- buflen = CFDataGetLength( data ) + 1;
- range = CFRangeMake( 0, buflen );
- toc_p = (struct _CDTOC *) malloc( buflen );
- if ( toc_p == NULL ) {
- fprintf( stderr, "Out of memory\n" );
- goto Exit;
- }
- else {
- CFDataGetBytes( data, range, (unsigned char *) toc_p );
- }
-
- /*
- fprintf( stderr, "Table of contents\n length %d first %d last %d\n",
- toc_p->length, toc_p->first_session, toc_p->last_session );
- */
-
- CFRelease( properties );
-
- }
-
-
- Exit:
-
- if ( service ) {
- IOObjectRelease( service );
- }
-
- return toc_p;
-
-}
-#endif
-
-#ifdef WIN32
-
-bool ReadCDSector(unsigned int hid, unsigned int tid, unsigned int lun, unsigned long frame, unsigned char *buf, int bufsize)
-{
- HANDLE hEventSRB;
- SRB_ExecSCSICmd srb;
- DWORD dwStatus;
-
- hEventSRB = CreateEvent(NULL, TRUE, FALSE, NULL);
-
- memset(&srb,0,sizeof(SRB_ExecSCSICmd));
- srb.SRB_Cmd = SC_EXEC_SCSI_CMD;
- srb.SRB_HaId = hid;
- srb.SRB_Target = tid;
- srb.SRB_Lun = lun;
- srb.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
- srb.SRB_SenseLen = SENSE_LEN;
- srb.SRB_PostProc = hEventSRB;
- srb.SRB_BufPointer = buf;
- srb.SRB_BufLen = bufsize;
- srb.SRB_CDBLen = 10;
- srb.CDBByte[0] = SCSI_READ10;
- srb.CDBByte[2] = (unsigned char) (frame>>24);
- srb.CDBByte[3] = (unsigned char) (frame>>16);
- srb.CDBByte[4] = (unsigned char) (frame>>8);
- srb.CDBByte[5] = (unsigned char) (frame);
- srb.CDBByte[7] = 0;
- srb.CDBByte[8] = 1; /* read 1 frames */
-
- ResetEvent(hEventSRB);
- dwStatus = SendASPI32Command((SRB *)&srb);
- if(dwStatus == SS_PENDING) {
- WaitForSingleObject(hEventSRB, 100000);
- }
- CloseHandle(hEventSRB);
- return (srb.SRB_TargStat == STATUS_GOOD);
-}
-
-int GetCDCapacity(unsigned int hid, unsigned int tid, unsigned int lun)
-{
- HANDLE hEventSRB;
- SRB_ExecSCSICmd srb;
- DWORD dwStatus;
- unsigned char buf[8];
-
- hEventSRB = CreateEvent(NULL, TRUE, FALSE, NULL);
-
- memset(&buf, 0, sizeof(buf));
- memset(&srb,0,sizeof(SRB_ExecSCSICmd));
- srb.SRB_Cmd = SC_EXEC_SCSI_CMD;
- srb.SRB_HaId = hid;
- srb.SRB_Target = tid;
- srb.SRB_Lun = lun;
- srb.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY;
- srb.SRB_SenseLen = SENSE_LEN;
- srb.SRB_PostProc = hEventSRB;
- srb.SRB_BufPointer = (unsigned char *)buf;
- srb.SRB_BufLen = 8;
- srb.SRB_CDBLen = 10;
- srb.CDBByte[0] = SCSI_READCDCAP;
- srb.CDBByte[2] = 0;
- srb.CDBByte[3] = 0;
- srb.CDBByte[4] = 0;
- srb.CDBByte[5] = 0;
- srb.CDBByte[8] = 0;
-
- ResetEvent(hEventSRB);
- dwStatus = SendASPI32Command((SRB *)&srb);
- if(dwStatus == SS_PENDING) {
- WaitForSingleObject(hEventSRB, 100000);
- }
-
- CloseHandle(hEventSRB);
- return ((buf[0] << 24) + (buf[1] << 16) + (buf[2] << 8) + buf[3]) * ((buf[4] << 24) + (buf[5] << 16) + (buf[6] << 8) + buf[7]);
-}
-
-#endif
-
-cdrom_interface::cdrom_interface(char *dev)
-{
- put("CD");
- settype(CDLOG);
- fd = -1; // File descriptor not yet allocated
-
- if ( dev == NULL )
- path = NULL;
- else {
- path = strdup(dev);
- }
- using_file=0;
-}
-
-void
-cdrom_interface::init(void) {
- BX_DEBUG(("Init $Id: cdrom.cc,v 1.66 2003/12/08 23:49:48 danielg4 Exp $"));
- BX_INFO(("file = '%s'",path));
-}
-
-cdrom_interface::~cdrom_interface(void)
-{
-#ifdef WIN32
-#else
- if (fd >= 0)
- close(fd);
-#endif
- if (path)
- free(path);
- BX_DEBUG(("Exit"));
-}
-
- bx_bool
-cdrom_interface::insert_cdrom(char *dev)
-{
- unsigned char buffer[BX_CD_FRAMESIZE];
- ssize_t ret;
-
- // Load CD-ROM. Returns false if CD is not ready.
- if (dev != NULL) path = strdup(dev);
- BX_INFO (("load cdrom with path=%s", path));
-#ifdef WIN32
- char drive[256];
- OSVERSIONINFO osi;
- if ( (path[1] == ':') && (strlen(path) == 2) )
- {
- osi.dwOSVersionInfoSize = sizeof(osi);
- GetVersionEx(&osi);
- if(osi.dwPlatformId == VER_PLATFORM_WIN32_NT) {
- // Use direct device access under windows NT/2k
-
- // With all the backslashes it's hard to see, but to open D: drive
- // the name would be: \\.\d:
- sprintf(drive, "\\\\.\\%s", path);
- using_file = 0;
- BX_INFO (("Using direct access for cdrom."));
- // This trick only works for Win2k and WinNT, so warn the user of that.
- } else {
- BX_INFO(("Using ASPI for cdrom. Drive letters are unused yet."));
- bUseASPI = TRUE;
- }
- }
- else
- {
- strcpy(drive,path);
- using_file = 1;
- bUseASPI = FALSE;
- BX_INFO (("Opening image file as a cd"));
- }
- if(bUseASPI) {
- DWORD d;
- UINT cdr, cnt, max;
- UINT i, j, k;
- SRB_HAInquiry sh;
- SRB_GDEVBlock sd;
- if (!hASPI) {
- hASPI = LoadLibrary("WNASPI32.DLL");
- }
- if(hASPI) {
- SendASPI32Command = (DWORD(*)(LPSRB))GetProcAddress( hASPI, "SendASPI32Command" );
- GetASPI32DLLVersion = (DWORD(*)(void))GetProcAddress( hASPI, "GetASPI32DLLVersion" );
- GetASPI32SupportInfo = (DWORD(*)(void))GetProcAddress( hASPI, "GetASPI32SupportInfo" );
-// BX_INFO(("Using first CDROM. Please upgrade your ASPI drivers to version 4.01 or later if you wish to specify a cdrom driver."));
-
- cdr = 0;
- bHaveDev = FALSE;
- d = GetASPI32SupportInfo();
- cnt = LOBYTE(LOWORD(d));
- for(i = 0; i < cnt; i++) {
- memset(&sh, 0, sizeof(sh));
- sh.SRB_Cmd = SC_HA_INQUIRY;
- sh.SRB_HaId = i;
- SendASPI32Command((LPSRB)&sh);
- if(sh.SRB_Status != SS_COMP)
- continue;
-
- max = (int)sh.HA_Unique[3];
- for(j = 0; j < max; j++) {
- for(k = 0; k < 8; k++) {
- memset(&sd, 0, sizeof(sd));
- sd.SRB_Cmd = SC_GET_DEV_TYPE;
- sd.SRB_HaId = i;
- sd.SRB_Target = j;
- sd.SRB_Lun = k;
- SendASPI32Command((LPSRB)&sd);
- if(sd.SRB_Status == SS_COMP) {
- if(sd.SRB_DeviceType == DTYPE_CDROM) {
- cdr++;
- if(cdr > cdromCount) {
- hid = i;
- tid = j;
- lun = k;
- cdromCount++;
- bHaveDev = TRUE;
- }
- }
- }
- if(bHaveDev) break;
- }
- if(bHaveDev) break;
- }
-
- }
- } else {
- BX_PANIC(("Could not load ASPI drivers, so cdrom access will fail"));
- }
- fd=1;
- } else {
- BX_INFO(("Using direct access for CDROM"));
- hFile=CreateFile((char *)&drive, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL);
- if (hFile !=(void *)0xFFFFFFFF)
- fd=1;
- }
-#elif defined(__APPLE__)
- if(strcmp(path, "drive") == 0)
- {
- mach_port_t masterPort = NULL;
- io_iterator_t mediaIterator;
- kern_return_t kernResult;
-
- BX_INFO(( "Insert CDROM" ));
-
- kernResult = FindEjectableCDMedia( &mediaIterator, &masterPort );
- if ( kernResult != KERN_SUCCESS ) {
- BX_INFO (("Unable to find CDROM"));
- return false;
- }
-
- kernResult = GetDeviceFilePath( mediaIterator, CDDevicePath, sizeof( CDDevicePath ) );
- if ( kernResult != KERN_SUCCESS ) {
- BX_INFO (("Unable to get CDROM device file path" ));
- return false;
- }
-
- // Here a cdrom was found so see if we can read from it.
- // At this point a failure will result in panic.
- if ( strlen( CDDevicePath ) ) {
- fd = open(CDDevicePath, O_RDONLY);
- }
- }
- else
- {
- fd = open(path, O_RDONLY);
- }
-#else
- // all platforms except win32
- fd = open(path, O_RDONLY);
-#endif
- if (fd < 0) {
- BX_ERROR(( "open cd failed for %s: %s", path, strerror(errno)));
- return(false);
- }
-
- // I just see if I can read a sector to verify that a
- // CD is in the drive and readable.
-#ifdef WIN32
- if(bUseASPI) {
- return ReadCDSector(hid, tid, lun, 0, buffer, BX_CD_FRAMESIZE);
- } else {
- if (!ReadFile(hFile, (void *) buffer, BX_CD_FRAMESIZE, (unsigned long *) &ret, NULL)) {
- CloseHandle(hFile);
- fd = -1;
- BX_DEBUG(( "insert_cdrom: read returns error." ));
- return(false);
- }
- }
-#else
- // do fstat to determine if it's a file or a device, then set using_file.
- struct stat stat_buf;
- ret = fstat (fd, &stat_buf);
- if (ret) {
- BX_PANIC (("fstat cdrom file returned error: %s", strerror (errno)));
- }
- if (S_ISREG (stat_buf.st_mode)) {
- using_file = 1;
- BX_INFO (("Opening image file %s as a cd.", path));
- } else {
- using_file = 0;
- BX_INFO (("Using direct access for cdrom."));
- }
-
- ret = read(fd, (char*) &buffer, BX_CD_FRAMESIZE);
- if (ret < 0) {
- close(fd);
- fd = -1;
- BX_DEBUG(( "insert_cdrom: read returns error: %s", strerror (errno) ));
- return(false);
- }
-#endif
- return(true);
-}
-
- int
-cdrom_interface::start_cdrom()
-{
- // Spin up the cdrom drive.
-
- if (fd >= 0) {
-#if defined(__NetBSD__)
- if (ioctl (fd, CDIOCSTART) < 0)
- BX_DEBUG(( "start_cdrom: start returns error: %s", strerror (errno) ));
- return(true);
-#else
- BX_INFO(("start_cdrom: your OS is not supported yet."));
- return(false); // OS not supported yet, return false always.
-#endif
- }
- return(false);
-}
-
- void
-cdrom_interface::eject_cdrom()
-{
- // Logically eject the CD. I suppose we could stick in
- // some ioctl() calls to really eject the CD as well.
-
- if (fd >= 0) {
-#if (defined(__OpenBSD__) || defined(__FreeBSD__))
- (void) ioctl (fd, CDIOCALLOW);
- if (ioctl (fd, CDIOCEJECT) < 0)
- BX_DEBUG(( "eject_cdrom: eject returns error." ));
-#endif
-
-#ifdef WIN32
-if (using_file == 0)
-{
- if(bUseASPI) {
- } else {
- DWORD lpBytesReturned;
- DeviceIoControl(hFile, IOCTL_STORAGE_EJECT_MEDIA, NULL, 0, NULL, 0, &lpBytesReturned, NULL);
- }
-}
-#else // WIN32
-
-#if __linux__
- if (!using_file)
- ioctl (fd, CDROMEJECT, NULL);
-#endif
-
- close(fd);
-#endif // WIN32
- fd = -1;
- }
-}
-
-
- bx_bool
-cdrom_interface::read_toc(uint8* buf, int* length, bx_bool msf, int start_track)
-{
- // Read CD TOC. Returns false if start track is out of bounds.
-
- if (fd < 0) {
- BX_PANIC(("cdrom: read_toc: file not open."));
- }
-
-#if defined(WIN32)
- if (1) { // This is a hack and works okay if there's one rom track only
-#else
- if (using_file) {
-#endif
- // From atapi specs : start track can be 0-63, AA
- if ((start_track > 1) && (start_track != 0xaa))
- return false;
-
- buf[2] = 1;
- buf[3] = 1;
-
- int len = 4;
- if (start_track <= 1) {
- buf[len++] = 0; // Reserved
- buf[len++] = 0x14; // ADR, control
- buf[len++] = 1; // Track number
- buf[len++] = 0; // Reserved
-
- // Start address
- if (msf) {
- buf[len++] = 0; // reserved
- buf[len++] = 0; // minute
- buf[len++] = 2; // second
- buf[len++] = 0; // frame
- } else {
- buf[len++] = 0;
- buf[len++] = 0;
- buf[len++] = 0;
- buf[len++] = 0; // logical sector 0
- }
- }
-
- // Lead out track
- buf[len++] = 0; // Reserved
- buf[len++] = 0x16; // ADR, control
- buf[len++] = 0xaa; // Track number
- buf[len++] = 0; // Reserved
-
- uint32 blocks = capacity();
-
- // Start address
- if (msf) {
- buf[len++] = 0; // reserved
- buf[len++] = (uint8)(((blocks + 150) / 75) / 60); // minute
- buf[len++] = (uint8)(((blocks + 150) / 75) % 60); // second
- buf[len++] = (uint8)((blocks + 150) % 75); // frame;
- } else {
- buf[len++] = (blocks >> 24) & 0xff;
- buf[len++] = (blocks >> 16) & 0xff;
- buf[len++] = (blocks >> 8) & 0xff;
- buf[len++] = (blocks >> 0) & 0xff;
- }
-
- buf[0] = ((len-2) >> 8) & 0xff;
- buf[1] = (len-2) & 0xff;
-
- *length = len;
-
- return true;
- }
- // all these implementations below are the platform-dependent code required
- // to read the TOC from a physical cdrom.
-#ifdef WIN32
- {
-/* #define IOCTL_CDROM_BASE FILE_DEVICE_CD_ROM
- #define IOCTL_CDROM_READ_TOC CTL_CODE(IOCTL_CDROM_BASE, 0x0000, METHOD_BUFFERED, FILE_READ_ACCESS)
- unsigned long iBytesReturned;
- DeviceIoControl(hFile, IOCTL_CDROM_READ_TOC, NULL, 0, NULL, 0, &iBytesReturned, NULL); */
- BX_ERROR (("WARNING: read_toc is not implemented, just returning length=1"));
- *length = 1;
- return true;
- }
-#elif __linux__ || defined(__sun)
- {
- struct cdrom_tochdr tochdr;
- if (ioctl(fd, CDROMREADTOCHDR, &tochdr))
- BX_PANIC(("cdrom: read_toc: READTOCHDR failed."));
-
- if ((start_track > tochdr.cdth_trk1) && (start_track != 0xaa))
- return false;
-
- buf[2] = tochdr.cdth_trk0;
- buf[3] = tochdr.cdth_trk1;
-
- if (start_track < tochdr.cdth_trk0)
- start_track = tochdr.cdth_trk0;
-
- int len = 4;
- for (int i = start_track; i <= tochdr.cdth_trk1; i++) {
- struct cdrom_tocentry tocentry;
- tocentry.cdte_format = (msf) ? CDROM_MSF : CDROM_LBA;
- tocentry.cdte_track = i;
- if (ioctl(fd, CDROMREADTOCENTRY, &tocentry))
- BX_PANIC(("cdrom: read_toc: READTOCENTRY failed."));
- buf[len++] = 0; // Reserved
- buf[len++] = (tocentry.cdte_adr << 4) | tocentry.cdte_ctrl ; // ADR, control
- buf[len++] = i; // Track number
- buf[len++] = 0; // Reserved
-
- // Start address
- if (msf) {
- buf[len++] = 0; // reserved
- buf[len++] = tocentry.cdte_addr.msf.minute;
- buf[len++] = tocentry.cdte_addr.msf.second;
- buf[len++] = tocentry.cdte_addr.msf.frame;
- } else {
- buf[len++] = (((unsigned)tocentry.cdte_addr.lba) >> 24) & 0xff;
- buf[len++] = (((unsigned)tocentry.cdte_addr.lba) >> 16) & 0xff;
- buf[len++] = (((unsigned)tocentry.cdte_addr.lba) >> 8) & 0xff;
- buf[len++] = (((unsigned)tocentry.cdte_addr.lba) >> 0) & 0xff;
- }
- }
-
- // Lead out track
- struct cdrom_tocentry tocentry;
- tocentry.cdte_format = (msf) ? CDROM_MSF : CDROM_LBA;
-#ifdef CDROM_LEADOUT
- tocentry.cdte_track = CDROM_LEADOUT;
-#else
- tocentry.cdte_track = 0xaa;
-#endif
- if (ioctl(fd, CDROMREADTOCENTRY, &tocentry))
- BX_PANIC(("cdrom: read_toc: READTOCENTRY lead-out failed."));
- buf[len++] = 0; // Reserved
- buf[len++] = (tocentry.cdte_adr << 4) | tocentry.cdte_ctrl ; // ADR, control
- buf[len++] = 0xaa; // Track number
- buf[len++] = 0; // Reserved
-
- // Start address
- if (msf) {
- buf[len++] = 0; // reserved
- buf[len++] = tocentry.cdte_addr.msf.minute;
- buf[len++] = tocentry.cdte_addr.msf.second;
- buf[len++] = tocentry.cdte_addr.msf.frame;
- } else {
- buf[len++] = (((unsigned)tocentry.cdte_addr.lba) >> 24) & 0xff;
- buf[len++] = (((unsigned)tocentry.cdte_addr.lba) >> 16) & 0xff;
- buf[len++] = (((unsigned)tocentry.cdte_addr.lba) >> 8) & 0xff;
- buf[len++] = (((unsigned)tocentry.cdte_addr.lba) >> 0) & 0xff;
- }
-
- buf[0] = ((len-2) >> 8) & 0xff;
- buf[1] = (len-2) & 0xff;
-
- *length = len;
-
- return true;
- }
-#elif (defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__))
- {
- struct ioc_toc_header h;
- struct ioc_read_toc_entry t;
-
- if (ioctl (fd, CDIOREADTOCHEADER, &h) < 0)
- BX_PANIC(("cdrom: read_toc: READTOCHDR failed."));
-
- if ((start_track > h.ending_track) && (start_track != 0xaa))
- return false;
-
- buf[2] = h.starting_track;
- buf[3] = h.ending_track;
-
- if (start_track < h.starting_track)
- start_track = h.starting_track;
-
- int len = 4;
- for (int i = start_track; i <= h.ending_track; i++) {
- struct cd_toc_entry tocentry;
- t.address_format = (msf) ? CD_MSF_FORMAT : CD_LBA_FORMAT;
- t.starting_track = i;
- t.data_len = sizeof(tocentry);
- t.data = &tocentry;
-
- if (ioctl (fd, CDIOREADTOCENTRYS, &t) < 0)
- BX_PANIC(("cdrom: read_toc: READTOCENTRY failed."));
-
- buf[len++] = 0; // Reserved
- buf[len++] = (tocentry.addr_type << 4) | tocentry.control ; // ADR, control
- buf[len++] = i; // Track number
- buf[len++] = 0; // Reserved
-
- // Start address
- if (msf) {
- buf[len++] = 0; // reserved
- buf[len++] = tocentry.addr.msf.minute;
- buf[len++] = tocentry.addr.msf.second;
- buf[len++] = tocentry.addr.msf.frame;
- } else {
- buf[len++] = (((unsigned)tocentry.addr.lba) >> 24) & 0xff;
- buf[len++] = (((unsigned)tocentry.addr.lba) >> 16) & 0xff;
- buf[len++] = (((unsigned)tocentry.addr.lba) >> 8) & 0xff;
- buf[len++] = (((unsigned)tocentry.addr.lba) >> 0) & 0xff;
- }
- }
-
- // Lead out track
- struct cd_toc_entry tocentry;
- t.address_format = (msf) ? CD_MSF_FORMAT : CD_LBA_FORMAT;
- t.starting_track = 0xaa;
- t.data_len = sizeof(tocentry);
- t.data = &tocentry;
-
- if (ioctl (fd, CDIOREADTOCENTRYS, &t) < 0)
- BX_PANIC(("cdrom: read_toc: READTOCENTRY lead-out failed."));
-
- buf[len++] = 0; // Reserved
- buf[len++] = (tocentry.addr_type << 4) | tocentry.control ; // ADR, control
- buf[len++] = 0xaa; // Track number
- buf[len++] = 0; // Reserved
-
- // Start address
- if (msf) {
- buf[len++] = 0; // reserved
- buf[len++] = tocentry.addr.msf.minute;
- buf[len++] = tocentry.addr.msf.second;
- buf[len++] = tocentry.addr.msf.frame;
- } else {
- buf[len++] = (((unsigned)tocentry.addr.lba) >> 24) & 0xff;
- buf[len++] = (((unsigned)tocentry.addr.lba) >> 16) & 0xff;
- buf[len++] = (((unsigned)tocentry.addr.lba) >> 8) & 0xff;
- buf[len++] = (((unsigned)tocentry.addr.lba) >> 0) & 0xff;
- }
-
- buf[0] = ((len-2) >> 8) & 0xff;
- buf[1] = (len-2) & 0xff;
-
- *length = len;
-
- return true;
- }
-#elif defined(__APPLE__)
- // Read CD TOC. Returns false if start track is out of bounds.
-
-#if 1
- {
- struct _CDTOC * toc = ReadTOC( CDDevicePath );
-
- if ((start_track > toc->last_session) && (start_track != 0xaa))
- return false;
-
- buf[2] = toc->first_session;
- buf[3] = toc->last_session;
-
- if (start_track < toc->first_session)
- start_track = toc->first_session;
-
- int len = 4;
- for (int i = start_track; i <= toc->last_session; i++) {
- buf[len++] = 0; // Reserved
- buf[len++] = toc->trackdesc[i].ctrl_adr ; // ADR, control
- buf[len++] = i; // Track number
- buf[len++] = 0; // Reserved
-
- // Start address
- if (msf) {
- buf[len++] = 0; // reserved
- buf[len++] = toc->trackdesc[i].address.minute;
- buf[len++] = toc->trackdesc[i].address.second;
- buf[len++] = toc->trackdesc[i].address.frame;
- } else {
- unsigned lba = (unsigned)(MSF_TO_LBA(toc->trackdesc[i].address));
- buf[len++] = (lba >> 24) & 0xff;
- buf[len++] = (lba >> 16) & 0xff;
- buf[len++] = (lba >> 8) & 0xff;
- buf[len++] = (lba >> 0) & 0xff;
- }
- }
-
- // Lead out track
- buf[len++] = 0; // Reserved
- buf[len++] = 0x16; // ADR, control
- buf[len++] = 0xaa; // Track number
- buf[len++] = 0; // Reserved
-
- uint32 blocks = capacity();
-
- // Start address
- if (msf) {
- buf[len++] = 0; // reserved
- buf[len++] = (uint8)(((blocks + 150) / 75) / 60); // minute
- buf[len++] = (uint8)(((blocks + 150) / 75) % 60); // second
- buf[len++] = (uint8)((blocks + 150) % 75); // frame;
- } else {
- buf[len++] = (blocks >> 24) & 0xff;
- buf[len++] = (blocks >> 16) & 0xff;
- buf[len++] = (blocks >> 8) & 0xff;
- buf[len++] = (blocks >> 0) & 0xff;
- }
-
- buf[0] = ((len-2) >> 8) & 0xff;
- buf[1] = (len-2) & 0xff;
-
- *length = len;
-
- return true;
-// BX_INFO(( "Read TOC - Not Implemented" ));
-// return false;
- }
-#else
- BX_INFO(( "Read TOC - Not Implemented" ));
- return false;
-#endif
-#else
- BX_INFO(("read_toc: your OS is not supported yet."));
- return(false); // OS not supported yet, return false always.
-#endif
-}
-
-
- uint32
-cdrom_interface::capacity()
-{
- // Return CD-ROM capacity. I believe you want to return
- // the number of blocks of capacity the actual media has.
-
-#if !defined WIN32
- // win32 has its own way of doing this
- if (using_file) {
- // return length of the image file
- struct stat stat_buf;
- int ret = fstat (fd, &stat_buf);
- if (ret) {
- BX_PANIC (("fstat on cdrom image returned err: %s", strerror(errno)));
- }
- BX_INFO (("cdrom size is %lld bytes", stat_buf.st_size));
- if ((stat_buf.st_size % 2048) != 0) {
- BX_ERROR (("expected cdrom image to be a multiple of 2048 bytes"));
- }
- return stat_buf.st_size / 2048;
- }
-#endif
-
-#ifdef __BEOS__
- return GetNumDeviceBlocks(fd, BX_CD_FRAMESIZE);
-#elif defined(__sun)
- {
- struct stat buf = {0};
-
- if (fd < 0) {
- BX_PANIC(("cdrom: capacity: file not open."));
- }
-
- if( fstat(fd, &buf) != 0 )
- BX_PANIC(("cdrom: capacity: stat() failed."));
-
- return(buf.st_size);
- }
-#elif (defined(__NetBSD__) || defined(__OpenBSD__))
- {
- // We just read the disklabel, imagine that...
- struct disklabel lp;
-
- if (fd < 0)
- BX_PANIC(("cdrom: capacity: file not open."));
-
- if (ioctl(fd, DIOCGDINFO, &lp) < 0)
- BX_PANIC(("cdrom: ioctl(DIOCGDINFO) failed"));
-
- BX_DEBUG(( "capacity: %u", lp.d_secperunit ));
- return(lp.d_secperunit);
- }
-#elif defined(__linux__)
- {
- // Read the TOC to get the data size, since BLKGETSIZE doesn't work on
- // non-ATAPI drives. This is based on Keith Jones code below.
- // <splite@purdue.edu> 21 June 2001
-
- int i, dtrk_lba, num_sectors;
- int dtrk = 0;
- struct cdrom_tochdr td;
- struct cdrom_tocentry te;
-
- if (fd < 0)
- BX_PANIC(("cdrom: capacity: file not open."));
-
- if (ioctl(fd, CDROMREADTOCHDR, &td) < 0)
- BX_PANIC(("cdrom: ioctl(CDROMREADTOCHDR) failed"));
-
- num_sectors = -1;
- dtrk_lba = -1;
-
- for (i = td.cdth_trk0; i <= td.cdth_trk1; i++) {
- te.cdte_track = i;
- te.cdte_format = CDROM_LBA;
- if (ioctl(fd, CDROMREADTOCENTRY, &te) < 0)
- BX_PANIC(("cdrom: ioctl(CDROMREADTOCENTRY) failed"));
-
- if (dtrk_lba != -1) {
- num_sectors = te.cdte_addr.lba - dtrk_lba;
- break;
- }
- if (te.cdte_ctrl & CDROM_DATA_TRACK) {
- dtrk = i;
- dtrk_lba = te.cdte_addr.lba;
- }
- }
-
- if (num_sectors < 0) {
- if (dtrk_lba != -1) {
- te.cdte_track = CDROM_LEADOUT;
- te.cdte_format = CDROM_LBA;
- if (ioctl(fd, CDROMREADTOCENTRY, &te) < 0)
- BX_PANIC(("cdrom: ioctl(CDROMREADTOCENTRY) failed"));
- num_sectors = te.cdte_addr.lba - dtrk_lba;
- } else
- BX_PANIC(("cdrom: no data track found"));
- }
-
- BX_INFO(("cdrom: Data track %d, length %d", dtrk, num_sectors));
-
- return(num_sectors);
-
- }
-#elif defined(__FreeBSD__)
- {
- // Read the TOC to get the size of the data track.
- // Keith Jones <freebsd.dev@blueyonder.co.uk>, 16 January 2000
-
-#define MAX_TRACKS 100
-
- int i, num_tracks, num_sectors;
- struct ioc_toc_header td;
- struct ioc_read_toc_entry rte;
- struct cd_toc_entry toc_buffer[MAX_TRACKS + 1];
-
- if (fd < 0)
- BX_PANIC(("cdrom: capacity: file not open."));
-
- if (ioctl(fd, CDIOREADTOCHEADER, &td) < 0)
- BX_PANIC(("cdrom: ioctl(CDIOREADTOCHEADER) failed"));
-
- num_tracks = (td.ending_track - td.starting_track) + 1;
- if (num_tracks > MAX_TRACKS)
- BX_PANIC(("cdrom: TOC is too large"));
-
- rte.address_format = CD_LBA_FORMAT;
- rte.starting_track = td.starting_track;
- rte.data_len = (num_tracks + 1) * sizeof(struct cd_toc_entry);
- rte.data = toc_buffer;
- if (ioctl(fd, CDIOREADTOCENTRYS, &rte) < 0)
- BX_PANIC(("cdrom: ioctl(CDIOREADTOCENTRYS) failed"));
-
- num_sectors = -1;
- for (i = 0; i < num_tracks; i++) {
- if (rte.data[i].control & 4) { /* data track */
- num_sectors = ntohl(rte.data[i + 1].addr.lba)
- - ntohl(rte.data[i].addr.lba);
- BX_INFO(( "cdrom: Data track %d, length %d",
- rte.data[i].track, num_sectors));
- break;
- }
- }
-
- if (num_sectors < 0)
- BX_PANIC(("cdrom: no data track found"));
-
- return(num_sectors);
-
- }
-#elif defined WIN32
- {
- if(bUseASPI) {
- return (GetCDCapacity(hid, tid, lun) / 2352);
- } else if(using_file) {
- ULARGE_INTEGER FileSize;
- FileSize.LowPart = GetFileSize(hFile, &FileSize.HighPart);
- return (FileSize.QuadPart / 2048);
- } else { /* direct device access */
- DWORD SectorsPerCluster;
- DWORD TotalNumOfClusters;
- GetDiskFreeSpace( path, &SectorsPerCluster, NULL, NULL, &TotalNumOfClusters);
- return (TotalNumOfClusters * SectorsPerCluster);
- }
- }
-#elif defined __APPLE__
-// Find the size of the first data track on the cd. This has produced
-// the same results as the linux version on every cd I have tried, about
-// 5. The differences here seem to be that the entries in the TOC when
-// retrieved from the IOKit interface appear in a reversed order when
-// compared with the linux READTOCENTRY ioctl.
- {
- // Return CD-ROM capacity. I believe you want to return
- // the number of bytes of capacity the actual media has.
-
- BX_INFO(( "Capacity" ));
-
- struct _CDTOC * toc = ReadTOC( CDDevicePath );
-
- if ( toc == NULL ) {
- BX_PANIC(( "capacity: Failed to read toc" ));
- }
-
- size_t toc_entries = ( toc->length - 2 ) / sizeof( struct _CDTOC_Desc );
-
- BX_DEBUG(( "reading %d toc entries\n", toc_entries ));
-
- int start_sector = -1;
- int data_track = -1;
-
- // Iterate through the list backward. Pick the first data track and
- // get the address of the immediately previous (or following depending
- // on how you look at it). The difference in the sector numbers
- // is returned as the sized of the data track.
- for ( int i=toc_entries - 1; i>=0; i-- ) {
-
- BX_DEBUG(( "session %d ctl_adr %d tno %d point %d lba %d z %d p lba %d\n",
- (int)toc->trackdesc[i].session,
- (int)toc->trackdesc[i].ctrl_adr,
- (int)toc->trackdesc[i].tno,
- (int)toc->trackdesc[i].point,
- MSF_TO_LBA( toc->trackdesc[i].address ),
- (int)toc->trackdesc[i].zero,
- MSF_TO_LBA(toc->trackdesc[i].p )));
-
- if ( start_sector != -1 ) {
-
- start_sector = MSF_TO_LBA(toc->trackdesc[i].p) - start_sector;
- break;
-
- }
-
- if (( toc->trackdesc[i].ctrl_adr >> 4) != 1 ) continue;
-
- if ( toc->trackdesc[i].ctrl_adr & 0x04 ) {
-
- data_track = toc->trackdesc[i].point;
-
- start_sector = MSF_TO_LBA(toc->trackdesc[i].p);
-
- }
-
- }
-
- free( toc );
-
- if ( start_sector == -1 ) {
- start_sector = 0;
- }
-
- BX_INFO(("first data track %d data size is %d", data_track, start_sector));
-
- return start_sector;
- }
-#else
- BX_ERROR(( "capacity: your OS is not supported yet." ));
- return(0);
-#endif
-}
-
- void BX_CPP_AttrRegparmN(2)
-cdrom_interface::read_block(uint8* buf, int lba)
-{
- // Read a single block from the CD
-
-#ifdef WIN32
- LARGE_INTEGER pos;
-#else
- off_t pos;
-#endif
- ssize_t n;
-
-#ifdef WIN32
- if(bUseASPI) {
- ReadCDSector(hid, tid, lun, lba, buf, BX_CD_FRAMESIZE);
- n = BX_CD_FRAMESIZE;
- } else {
- pos.QuadPart = (LONGLONG)lba*BX_CD_FRAMESIZE;
- pos.LowPart = SetFilePointer(hFile, pos.LowPart, &pos.HighPart, SEEK_SET);
- if ((pos.LowPart == 0xffffffff) && (GetLastError() != NO_ERROR)) {
- BX_PANIC(("cdrom: read_block: SetFilePointer returned error."));
- }
- ReadFile(hFile, (void *) buf, BX_CD_FRAMESIZE, (unsigned long *) &n, NULL);
- }
-#elif defined(__APPLE__)
-#define CD_SEEK_DISTANCE kCDSectorSizeWhole
- if(using_file)
- {
- pos = lseek(fd, lba*BX_CD_FRAMESIZE, SEEK_SET);
- if (pos < 0) {
- BX_PANIC(("cdrom: read_block: lseek returned error."));
- }
- n = read(fd, buf, BX_CD_FRAMESIZE);
- }
- else
- {
- // This seek will leave us 16 bytes from the start of the data
- // hence the magic number.
- pos = lseek(fd, lba*CD_SEEK_DISTANCE + 16, SEEK_SET);
- if (pos < 0) {
- BX_PANIC(("cdrom: read_block: lseek returned error."));
- }
- n = read(fd, buf, CD_FRAMESIZE);
- }
-#else
- pos = lseek(fd, lba*BX_CD_FRAMESIZE, SEEK_SET);
- if (pos < 0) {
- BX_PANIC(("cdrom: read_block: lseek returned error."));
- }
- n = read(fd, (char*) buf, BX_CD_FRAMESIZE);
-#endif
-
- if (n != BX_CD_FRAMESIZE) {
- BX_PANIC(("cdrom: read_block: read returned %d",
- (int) n));
- }
-}
-
-#endif /* if BX_SUPPORT_CDROM */
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: cdrom.h,v 1.13 2003/08/19 00:37:03 cbothamy Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-// Header file for low-level OS specific CDROM emulation
-
-
-class cdrom_interface : public logfunctions {
-public:
- cdrom_interface(char *dev);
- ~cdrom_interface(void);
- void init(void);
-
- // Load CD-ROM. Returns false if CD is not ready.
- bx_bool insert_cdrom(char *dev = NULL);
-
- // Logically eject the CD.
- void eject_cdrom();
-
- // Read CD TOC. Returns false if start track is out of bounds.
- bx_bool read_toc(uint8* buf, int* length, bx_bool msf, int start_track);
-
- // Return CD-ROM capacity (in 2048 byte frames)
- uint32 capacity();
-
- // Read a single block from the CD
- void read_block(uint8* buf, int lba) BX_CPP_AttrRegparmN(2);
-
- // Start (spin up) the CD.
- int start_cdrom();
-
-private:
- int fd;
- char *path;
-
- int using_file;
-#ifdef WIN32
- HANDLE hFile;
- int hid;
- int tid;
- int lun;
-#endif
- };
-
+++ /dev/null
-#ifndef CDROM_BEOS_H
-#define CDROM_BEOS_H
-
-#include <stddef.h> //for off_t
-
-off_t GetNumDeviceBlocks(int fd, int block_size);
-int GetLogicalBlockSize(int fd);
-int GetDeviceBlockSize(int fd);
-
-#endif
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: cmos.cc,v 1.44 2003/12/27 13:43:41 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-
-
-
-// Define BX_PLUGGABLE in files that can be compiled into plugins. For
-// platforms that require a special tag on exported symbols, BX_PLUGGABLE
-// is used to know when we are exporting symbols and when we are importing.
-#define BX_PLUGGABLE
-
-#include "bochs.h"
-
-#define LOG_THIS theCmosDevice->
-
-bx_cmos_c *theCmosDevice = NULL;
-
-// CMOS register definitions from Ralf Brown's interrupt list v6.1, in a file
-// called cmos.lst. In cases where there are multiple uses for a given
-// register in the interrupt list, I only listed the purpose that Bochs
-// actually uses it for, but I wrote "alternatives" next to it.
-#define REG_SEC 0x00
-#define REG_SEC_ALARM 0x01
-#define REG_MIN 0x02
-#define REG_MIN_ALARM 0x03
-#define REG_HOUR 0x04
-#define REG_HOUR_ALARM 0x05
-#define REG_WEEK_DAY 0x06
-#define REG_MONTH_DAY 0x07
-#define REG_MONTH 0x08
-#define REG_YEAR 0x09
-#define REG_STAT_A 0x0a
-#define REG_STAT_B 0x0b
-#define REG_STAT_C 0x0c
-#define REG_STAT_D 0x0d
-#define REG_DIAGNOSTIC_STATUS 0x0e /* alternatives */
-#define REG_SHUTDOWN_STATUS 0x0f
-#define REG_EQUIPMENT_BYTE 0x14
-#define REG_CSUM_HIGH 0x2e
-#define REG_CSUM_LOW 0x2f
-#define REG_IBM_CENTURY_BYTE 0x32 /* alternatives */
-#define REG_IBM_PS2_CENTURY_BYTE 0x37 /* alternatives */
-
-// Bochs CMOS map (to be completed)
-//
-// Idx Len Description
-// 0x15 2 Base memory in 1k
-// 0x17 2 Memory size above 1M in 1k
-// 0x30 2 Memory size above 1M in 1k
-// 0x34 2 Memory size above 16M in 64k
-//
-
-// check that BX_NUM_CMOS_REGS is 64 or 128
-#if (BX_NUM_CMOS_REGS == 64)
-#elif (BX_NUM_CMOS_REGS == 128)
-#else
-#error "Invalid BX_NUM_CMOS_REGS value in config.h"
-#endif
-
-
- int
-libcmos_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[])
-{
- theCmosDevice = new bx_cmos_c ();
- bx_devices.pluginCmosDevice = theCmosDevice;
- BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theCmosDevice, BX_PLUGIN_CMOS);
- return(0); // Success
-}
-
- void
-libcmos_LTX_plugin_fini(void)
-{
-}
-
-bx_cmos_c::bx_cmos_c(void)
-{
- put("CMOS");
- settype(CMOSLOG);
-
- unsigned i;
- for (i=0; i<BX_NUM_CMOS_REGS; i++)
- s.reg[i] = 0;
- s.periodic_timer_index = BX_NULL_TIMER_HANDLE;
- s.one_second_timer_index = BX_NULL_TIMER_HANDLE;
- s.uip_timer_index = BX_NULL_TIMER_HANDLE;
-}
-
-bx_cmos_c::~bx_cmos_c(void)
-{
- BX_DEBUG(("Exit."));
-}
-
-
- void
-bx_cmos_c::init(void)
-{
- BX_DEBUG(("Init $Id: cmos.cc,v 1.44 2003/12/27 13:43:41 vruppert Exp $"));
- // CMOS RAM & RTC
-
- DEV_register_ioread_handler(this, read_handler, 0x0070, "CMOS RAM", 1);
- DEV_register_ioread_handler(this, read_handler, 0x0071, "CMOS RAM", 1);
- DEV_register_iowrite_handler(this, write_handler, 0x0070, "CMOS RAM", 1);
- DEV_register_iowrite_handler(this, write_handler, 0x0071, "CMOS RAM", 1);
- DEV_register_irq(8, "CMOS RTC");
- if (BX_CMOS_THIS s.periodic_timer_index == BX_NULL_TIMER_HANDLE) {
- BX_CMOS_THIS s.periodic_timer_index =
- DEV_register_timer(this, periodic_timer_handler,
- 1000000, 1,0, "cmos"); // continuous, not-active
- }
- if (BX_CMOS_THIS s.one_second_timer_index == BX_NULL_TIMER_HANDLE) {
- BX_CMOS_THIS s.one_second_timer_index =
- DEV_register_timer(this, one_second_timer_handler,
- 1000000, 1,0, "cmos"); // continuous, not-active
- }
- if (BX_CMOS_THIS s.uip_timer_index == BX_NULL_TIMER_HANDLE) {
- BX_CMOS_THIS s.uip_timer_index =
- DEV_register_timer(this, uip_timer_handler,
- 244, 0, 0, "cmos"); // one-shot, not-active
- }
-
-#if BX_USE_SPECIFIED_TIME0 != 0
- // ??? this will not be correct for using an image file.
- // perhaps take values in CMOS and work backwards to find
- // s.timeval from values read in.
- BX_CMOS_THIS s.timeval = BX_USE_SPECIFIED_TIME0;
-
-#else // BX_USE_SPECIFIED_TIME0 != 0
-
- // localtime
- if (bx_options.clock.Otime0->get () == BX_CLOCK_TIME0_LOCAL) {
- BX_INFO(("Using local time for initial clock"));
- BX_CMOS_THIS s.timeval = time(NULL);
- }
- // utc
- else if (bx_options.clock.Otime0->get () == BX_CLOCK_TIME0_UTC) {
- bx_bool utc_ok = 0;
-
- BX_INFO(("Using utc time for initial clock"));
-
- BX_CMOS_THIS s.timeval = time(NULL);
-
-#if BX_HAVE_GMTIME
-#if BX_HAVE_MKTIME
- struct tm *utc_holder = gmtime(&BX_CMOS_THIS s.timeval);
- utc_holder->tm_isdst = -1;
- utc_ok = 1;
- BX_CMOS_THIS s.timeval = mktime(utc_holder);
-#elif BX_HAVE_TIMELOCAL
- struct tm *utc_holder = gmtime(&BX_CMOS_THIS s.timeval);
- utc_holder->tm_isdst = 0; // XXX Is this correct???
- utc_ok = 1;
- BX_CMOS_THIS s.timeval = timelocal(utc_holder);
-#endif //BX_HAVE_MKTIME
-#endif //BX_HAVE_GMTIME
-
- if (!utc_ok) {
- BX_ERROR(("UTC time is not supported on your platform. Using current time(NULL)"));
- }
- }
- else {
- BX_INFO(("Using specified time for initial clock"));
- BX_CMOS_THIS s.timeval = bx_options.clock.Otime0->get ();
- }
-#endif // BX_USE_SPECIFIED_TIME0 != 0
-
- char *tmptime;
- while( (tmptime = strdup(ctime(&(BX_CMOS_THIS s.timeval)))) == NULL) {
- BX_PANIC(("Out of memory."));
- }
- tmptime[strlen(tmptime)-1]='\0';
-
- BX_INFO(("Setting initial clock to: %s (time0=%u)", tmptime, (Bit32u)BX_CMOS_THIS s.timeval));
-
- update_clock();
- BX_CMOS_THIS s.timeval_change = 0;
-
- // load CMOS from image file if requested.
- if (bx_options.cmos.OcmosImage->get ()) {
- // CMOS image file requested
- int fd, ret;
- struct stat stat_buf;
-
- fd = open(bx_options.cmos.Opath->getptr (), O_RDONLY
-#ifdef O_BINARY
- | O_BINARY
-#endif
- );
- if (fd < 0) {
- BX_PANIC(("trying to open cmos image file '%s'",
- bx_options.cmos.Opath->getptr ()));
- }
- ret = fstat(fd, &stat_buf);
- if (ret) {
- BX_PANIC(("CMOS: could not fstat() image file."));
- }
- if (stat_buf.st_size != BX_NUM_CMOS_REGS) {
- BX_PANIC(("CMOS: image file not same size as BX_NUM_CMOS_REGS."));
- }
-
- ret = ::read(fd, (bx_ptr_t) BX_CMOS_THIS s.reg, BX_NUM_CMOS_REGS);
- if (ret != BX_NUM_CMOS_REGS) {
- BX_PANIC(("CMOS: error reading cmos file."));
- }
- close(fd);
- BX_INFO(("successfuly read from image file '%s'.",
- bx_options.cmos.Opath->getptr ()));
- }
- else {
- // CMOS values generated
- BX_CMOS_THIS s.reg[REG_STAT_A] = 0x26;
- BX_CMOS_THIS s.reg[REG_STAT_B] = 0x02;
- BX_CMOS_THIS s.reg[REG_STAT_C] = 0x00;
- BX_CMOS_THIS s.reg[REG_STAT_D] = 0x80;
-#if BX_SUPPORT_FPU == 1
- BX_CMOS_THIS s.reg[REG_EQUIPMENT_BYTE] |= 0x02;
-#endif
- }
-}
-
- void
-bx_cmos_c::reset(unsigned type)
-{
- BX_CMOS_THIS s.cmos_mem_address = 0;
-
- // RESET affects the following registers:
- // CRA: no effects
- // CRB: bits 4,5,6 forced to 0
- // CRC: bits 4,5,6,7 forced to 0
- // CRD: no effects
- BX_CMOS_THIS s.reg[REG_STAT_B] &= 0x8f;
- BX_CMOS_THIS s.reg[REG_STAT_C] = 0;
-
- // One second timer for updating clock & alarm functions
- bx_pc_system.activate_timer(BX_CMOS_THIS s.one_second_timer_index,
- 1000000, 1);
-
- // handle periodic interrupt rate select
- BX_CMOS_THIS CRA_change();
-}
-
- void
-bx_cmos_c::CRA_change(void)
-{
- unsigned nibble;
-
- // Periodic Interrupt timer
- nibble = BX_CMOS_THIS s.reg[REG_STAT_A] & 0x0f;
- if (nibble == 0) {
- // No Periodic Interrupt Rate when 0, deactivate timer
- bx_pc_system.deactivate_timer(BX_CMOS_THIS s.periodic_timer_index);
- BX_CMOS_THIS s.periodic_interval_usec = (Bit32u) -1; // max value
- }
- else {
- // values 0001b and 0010b are the same as 1000b and 1001b
- if (nibble <= 2)
- nibble += 7;
- BX_CMOS_THIS s.periodic_interval_usec = (unsigned) (1000000.0L /
- (32768.0L / (1 << (nibble - 1))));
-
- // if Periodic Interrupt Enable bit set, activate timer
- if ( BX_CMOS_THIS s.reg[REG_STAT_B] & 0x40 )
- bx_pc_system.activate_timer(BX_CMOS_THIS s.periodic_timer_index,
- BX_CMOS_THIS s.periodic_interval_usec, 1);
- else
- bx_pc_system.deactivate_timer(BX_CMOS_THIS s.periodic_timer_index);
- }
-}
-
-
- // static IO port read callback handler
- // redirects to non-static class handler to avoid virtual functions
-
- Bit32u
-bx_cmos_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len)
-{
-#if !BX_USE_CMOS_SMF
- bx_cmos_c *class_ptr = (bx_cmos_c *) this_ptr;
-
- return( class_ptr->read(address, io_len) );
-}
-
- Bit32u
-bx_cmos_c::read(Bit32u address, unsigned io_len)
-{
-#else
- UNUSED(this_ptr);
-#endif
- Bit8u ret8;
-
- if (bx_dbg.cmos)
- BX_INFO(("CMOS read of CMOS register 0x%02x",
- (unsigned) BX_CMOS_THIS s.cmos_mem_address));
-
-
- switch (address) {
- case 0x0070:
- BX_INFO(("read of index port 0x70. returning 0xff"));
- // Volker says his boxes return 0xff
- //ret8 = BX_CMOS_THIS s.cmos_mem_address;
- return(0xff);
- break;
- case 0x0071:
- if (BX_CMOS_THIS s.cmos_mem_address >= BX_NUM_CMOS_REGS) {
- BX_PANIC(("unsupported cmos io read, register(0x%02x)!",
- (unsigned) BX_CMOS_THIS s.cmos_mem_address));
- }
-
- ret8 = BX_CMOS_THIS s.reg[BX_CMOS_THIS s.cmos_mem_address];
- // all bits of Register C are cleared after a read occurs.
- if (BX_CMOS_THIS s.cmos_mem_address == REG_STAT_C) {
- BX_CMOS_THIS s.reg[REG_STAT_C] = 0x00;
- DEV_pic_lower_irq(8);
- }
- return(ret8);
- break;
-
- default:
- BX_PANIC(("unsupported cmos read, address=0x%04x!",
- (unsigned) address));
- return(0);
- break;
- }
-}
-
-
- // static IO port write callback handler
- // redirects to non-static class handler to avoid virtual functions
-
- void
-bx_cmos_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len)
-{
-#if !BX_USE_CMOS_SMF
- bx_cmos_c *class_ptr = (bx_cmos_c *) this_ptr;
-
- class_ptr->write(address, value, io_len);
-}
-
- void
-bx_cmos_c::write(Bit32u address, Bit32u value, unsigned io_len)
-{
-#else
- UNUSED(this_ptr);
-#endif // !BX_USE_CMOS_SMF
-
- if (bx_dbg.cmos)
- BX_INFO(("CMOS write to address: 0x%04x = 0x%02x",
- (unsigned) address, (unsigned) value));
-
-
- switch (address) {
- case 0x0070:
-#if (BX_NUM_CMOS_REGS == 64)
- BX_CMOS_THIS s.cmos_mem_address = value & 0x3F;
-#else
- BX_CMOS_THIS s.cmos_mem_address = value & 0x7F;
-#endif
- break;
-
- case 0x0071:
- if (BX_CMOS_THIS s.cmos_mem_address >= BX_NUM_CMOS_REGS) {
- BX_PANIC(("unsupported cmos io write, register(0x%02x) = 0x%02x !",
- (unsigned) BX_CMOS_THIS s.cmos_mem_address, (unsigned) value));
- return;
- }
- switch (BX_CMOS_THIS s.cmos_mem_address) {
- case REG_SEC_ALARM: // seconds alarm
- case REG_MIN_ALARM: // minutes alarm
- case REG_HOUR_ALARM: // hours alarm
- BX_CMOS_THIS s.reg[BX_CMOS_THIS s.cmos_mem_address] = value;
- BX_DEBUG(("alarm time changed to %02x:%02x:%02x", BX_CMOS_THIS s.reg[REG_HOUR_ALARM],
- BX_CMOS_THIS s.reg[REG_MIN_ALARM], BX_CMOS_THIS s.reg[REG_SEC_ALARM]));
- return;
- break;
-
- case REG_SEC: // seconds
- case REG_MIN: // minutes
- case REG_HOUR: // hours
- case REG_WEEK_DAY: // day of the week
- case REG_MONTH_DAY: // day of the month
- case REG_MONTH: // month
- case REG_YEAR: // year
- case REG_IBM_CENTURY_BYTE: // century
- case REG_IBM_PS2_CENTURY_BYTE: // century (PS/2)
- //BX_INFO(("write reg 0x%02x: value = 0x%02x",
- // (unsigned) BX_CMOS_THIS s.cmos_mem_address, (unsigned) value);
- BX_CMOS_THIS s.reg[BX_CMOS_THIS s.cmos_mem_address] = value;
- if (BX_CMOS_THIS s.cmos_mem_address == REG_IBM_PS2_CENTURY_BYTE) {
- BX_CMOS_THIS s.reg[REG_IBM_CENTURY_BYTE] = value;
- }
- if (BX_CMOS_THIS s.reg[REG_STAT_B] & 0x80) {
- BX_CMOS_THIS s.timeval_change = 1;
- } else {
- update_timeval();
- }
- return;
- break;
-
- case REG_STAT_A: // Control Register A
- // bit 7: Update in Progress (read-only)
- // 1 = signifies time registers will be updated within 244us
- // 0 = time registers will not occur before 244us
- // note: this bit reads 0 when CRB bit 7 is 1
- // bit 6..4: Divider Chain Control
- // 000 oscillator disabled
- // 001 oscillator disabled
- // 010 Normal operation
- // 011 TEST
- // 100 TEST
- // 101 TEST
- // 110 Divider Chain RESET
- // 111 Divider Chain RESET
- // bit 3..0: Periodic Interrupt Rate Select
- // 0000 None
- // 0001 3.90625 ms
- // 0010 7.8125 ms
- // 0011 122.070 us
- // 0100 244.141 us
- // 0101 488.281 us
- // 0110 976.562 us
- // 0111 1.953125 ms
- // 1000 3.90625 ms
- // 1001 7.8125 ms
- // 1010 15.625 ms
- // 1011 31.25 ms
- // 1100 62.5 ms
- // 1101 125 ms
- // 1110 250 ms
- // 1111 500 ms
-
- unsigned dcc;
- dcc = (value >> 4) & 0x07;
- if ((dcc & 0x06) == 0x06) {
- BX_INFO(("CRA: divider chain RESET"));
- } else if (dcc != 0x02) {
- BX_PANIC(("CRA: divider chain control 0x%02x", dcc));
- }
- BX_CMOS_THIS s.reg[REG_STAT_A] &= 0x80;
- BX_CMOS_THIS s.reg[REG_STAT_A] |= (value & 0x7f);
- BX_CMOS_THIS CRA_change();
- return;
- break;
-
- case REG_STAT_B: // Control Register B
- // bit 0: Daylight Savings Enable
- // 1 = enable daylight savings
- // 0 = disable daylight savings
- // bit 1: 24/12 houre mode
- // 1 = 24 hour format
- // 0 = 12 hour format
- // bit 2: Data Mode
- // 1 = binary format
- // 0 = BCD format
- // bit 3: "square wave enable"
- // Not supported and always read as 0
- // bit 4: Update Ended Interrupt Enable
- // 1 = enable generation of update ended interrupt
- // 0 = disable
- // bit 5: Alarm Interrupt Enable
- // 1 = enable generation of alarm interrupt
- // 0 = disable
- // bit 6: Periodic Interrupt Enable
- // 1 = enable generation of periodic interrupt
- // 0 = disable
- // bit 7: Set mode
- // 1 = user copy of time is "frozen" allowing time registers
- // to be accessed without regard for an occurance of an update
- // 0 = time updates occur normally
-
- // can not handle binary or 12-hour mode yet.
- if (value & 0x04)
- BX_PANIC(("write status reg B, binary format enabled."));
- if ( !(value & 0x02) )
- BX_PANIC(("write status reg B, 12 hour mode enabled."));
-
- value &= 0xf7; // bit3 always 0
- // Note: setting bit 7 clears bit 4
- if (value & 0x80)
- value &= 0xef;
-
- unsigned prev_CRB;
- prev_CRB = BX_CMOS_THIS s.reg[REG_STAT_B];
- BX_CMOS_THIS s.reg[REG_STAT_B] = value;
- if ( (prev_CRB & 0x40) != (value & 0x40) ) {
- // Periodic Interrupt Enabled changed
- if (prev_CRB & 0x40) {
- // transition from 1 to 0, deactivate timer
- bx_pc_system.deactivate_timer(
- BX_CMOS_THIS s.periodic_timer_index);
- }
- else {
- // transition from 0 to 1
- // if rate select is not 0, activate timer
- if ( (BX_CMOS_THIS s.reg[REG_STAT_A] & 0x0f) != 0 ) {
- bx_pc_system.activate_timer(
- BX_CMOS_THIS s.periodic_timer_index,
- BX_CMOS_THIS s.periodic_interval_usec, 1);
- }
- }
- }
- if ( (prev_CRB >= 0x80) && (value < 0x80) && BX_CMOS_THIS s.timeval_change) {
- update_timeval();
- BX_CMOS_THIS s.timeval_change = 0;
- }
- return;
- break;
-
- case REG_STAT_C: // Control Register C
- case REG_STAT_D: // Control Register D
- BX_ERROR(("write to control register 0x%02x (read-only)",
- BX_CMOS_THIS s.cmos_mem_address));
- break;
-
- case REG_DIAGNOSTIC_STATUS:
- BX_DEBUG(("write register 0x0e: 0x%02x", (unsigned) value));
- break;
-
- case REG_SHUTDOWN_STATUS:
- switch (value) {
- case 0x00: /* proceed with normal POST (soft reset) */
- BX_DEBUG(("Reg 0Fh(00): shutdown action = normal POST"));
- break;
- case 0x01: /* shutdown after memory size check */
- BX_DEBUG(("Reg 0Fh(01): request to change shutdown action"
- " to shutdown after memory size check"));
- case 0x02: /* shutdown after successful memory test */
- BX_DEBUG(("Reg 0Fh(02): request to change shutdown action"
- " to shutdown after successful memory test"));
- break;
- case 0x03: /* shutdown after failed memory test */
- BX_DEBUG(("Reg 0Fh(03): request to change shutdown action"
- " to shutdown after successful memory test"));
- break;
- case 0x04: /* jump to disk bootstrap routine */
- BX_DEBUG(("Reg 0Fh(04): request to change shutdown action "
- "to jump to disk bootstrap routine."));
- break;
- case 0x05: /* flush keyboard (issue EOI) and jump via 40h:0067h */
- BX_DEBUG(("Reg 0Fh(05): request to change shutdown action "
- "to flush keyboard (issue EOI) and jump via 40h:0067h."));
- break;
- case 0x06:
- BX_DEBUG(("Reg 0Fh(06): Shutdown after memory test !"));
- break;
- case 0x07: /* reset (after failed test in virtual mode) */
- BX_DEBUG(("Reg 0Fh(07): request to change shutdown action "
- "to reset (after failed test in virtual mode)."));
- break;
- case 0x08: /* used by POST during protected-mode RAM test (return to POST) */
- BX_DEBUG(("Reg 0Fh(08): request to change shutdown action "
- "to return to POST (used by POST during protected-mode RAM test)."));
- break;
- case 0x09: /* return to BIOS extended memory block move
- (interrupt 15h, func 87h was in progress) */
- BX_DEBUG(("Reg 0Fh(09): request to change shutdown action "
- "to return to BIOS extended memory block move."));
- break;
- case 0x0a: /* jump to DWORD pointer at 40:67 */
- BX_DEBUG(("Reg 0Fh(0a): request to change shutdown action"
- " to jump to DWORD at 40:67"));
- break;
- case 0x0b: /* iret to DWORD pointer at 40:67 */
- BX_DEBUG(("Reg 0Fh(0b): request to change shutdown action"
- " to iret to DWORD at 40:67"));
- break;
- case 0x0c: /* retf to DWORD pointer at 40:67 */
- BX_DEBUG(("Reg 0Fh(0c): request to change shutdown action"
- " to retf to DWORD at 40:67"));
- break;
- default:
- BX_PANIC(("unsupported cmos io write to reg F, case 0x%02x!",
- (unsigned) value));
- break;
- }
- break;
-
- default:
- BX_DEBUG(("write reg 0x%02x: value = 0x%02x",
- (unsigned) BX_CMOS_THIS s.cmos_mem_address, (unsigned) value));
- break;
- }
-
- BX_CMOS_THIS s.reg[BX_CMOS_THIS s.cmos_mem_address] = value;
- break;
- }
-}
-
-
- void
-bx_cmos_c::checksum_cmos(void)
-{
- unsigned i;
- Bit16u sum;
-
- sum = 0;
- for (i=0x10; i<=0x2d; i++) {
- sum += BX_CMOS_THIS s.reg[i];
- }
- BX_CMOS_THIS s.reg[REG_CSUM_HIGH] = (sum >> 8) & 0xff; /* checksum high */
- BX_CMOS_THIS s.reg[REG_CSUM_LOW] = (sum & 0xff); /* checksum low */
-}
-
- void
-bx_cmos_c::periodic_timer_handler(void *this_ptr)
-{
- bx_cmos_c *class_ptr = (bx_cmos_c *) this_ptr;
-
- class_ptr->periodic_timer();
-}
-
- void
-bx_cmos_c::periodic_timer()
-{
- // if periodic interrupts are enabled, trip IRQ 8, and
- // update status register C
- if (BX_CMOS_THIS s.reg[REG_STAT_B] & 0x40) {
- BX_CMOS_THIS s.reg[REG_STAT_C] |= 0xc0; // Interrupt Request, Periodic Int
- DEV_pic_raise_irq(8);
- }
-}
-
- void
-bx_cmos_c::one_second_timer_handler(void *this_ptr)
-{
- bx_cmos_c *class_ptr = (bx_cmos_c *) this_ptr;
-
- class_ptr->one_second_timer();
-}
-
- void
-bx_cmos_c::one_second_timer()
-{
- // divider chain reset - RTC stopped
- if ((BX_CMOS_THIS s.reg[REG_STAT_A] & 0x60) == 0x60)
- return;
-
- // update internal time/date buffer
- BX_CMOS_THIS s.timeval++;
-
- // Dont update CMOS user copy of time/date if CRB bit7 is 1
- // Nothing else do to
- if (BX_CMOS_THIS s.reg[REG_STAT_B] & 0x80)
- return;
-
- BX_CMOS_THIS s.reg[REG_STAT_A] |= 0x80; // set UIP bit
-
- // UIP timer for updating clock & alarm functions
- bx_pc_system.activate_timer(BX_CMOS_THIS s.uip_timer_index,
- 244, 0);
-}
-
- void
-bx_cmos_c::uip_timer_handler(void *this_ptr)
-{
- bx_cmos_c *class_ptr = (bx_cmos_c *) this_ptr;
-
- class_ptr->uip_timer();
-}
-
- void
-bx_cmos_c::uip_timer()
-{
- update_clock();
-
- // if update interrupts are enabled, trip IRQ 8, and
- // update status register C
- if (BX_CMOS_THIS s.reg[REG_STAT_B] & 0x10) {
- BX_CMOS_THIS s.reg[REG_STAT_C] |= 0x90; // Interrupt Request, Update Ended
- DEV_pic_raise_irq(8);
- }
-
- // compare CMOS user copy of time/date to alarm time/date here
- if (BX_CMOS_THIS s.reg[REG_STAT_B] & 0x20) {
- // Alarm interrupts enabled
- bx_bool alarm_match = 1;
- if ( (BX_CMOS_THIS s.reg[REG_SEC_ALARM] & 0xc0) != 0xc0 ) {
- // seconds alarm not in dont care mode
- if (BX_CMOS_THIS s.reg[REG_SEC] != BX_CMOS_THIS s.reg[REG_SEC_ALARM])
- alarm_match = 0;
- }
- if ( (BX_CMOS_THIS s.reg[REG_MIN_ALARM] & 0xc0) != 0xc0 ) {
- // minutes alarm not in dont care mode
- if (BX_CMOS_THIS s.reg[REG_MIN] != BX_CMOS_THIS s.reg[REG_MIN_ALARM])
- alarm_match = 0;
- }
- if ( (BX_CMOS_THIS s.reg[REG_HOUR_ALARM] & 0xc0) != 0xc0 ) {
- // hours alarm not in dont care mode
- if (BX_CMOS_THIS s.reg[REG_HOUR] != BX_CMOS_THIS s.reg[REG_HOUR_ALARM])
- alarm_match = 0;
- }
- if (alarm_match) {
- BX_CMOS_THIS s.reg[REG_STAT_C] |= 0xa0; // Interrupt Request, Alarm Int
- DEV_pic_raise_irq(8);
- }
- }
- BX_CMOS_THIS s.reg[REG_STAT_A] &= 0x7f; // clear UIP bit
-}
-
-
- void
-bx_cmos_c::update_clock()
-{
- struct tm *time_calendar;
- unsigned year, month, day, century;
- Bit8u val_bcd;
-
- time_calendar = localtime(& BX_CMOS_THIS s.timeval);
-
- // update seconds
- val_bcd =
- ((time_calendar->tm_sec / 10) << 4) |
- (time_calendar->tm_sec % 10);
- BX_CMOS_THIS s.reg[REG_SEC] = val_bcd;
-
- // update minutes
- val_bcd =
- ((time_calendar->tm_min / 10) << 4) |
- (time_calendar->tm_min % 10);
- BX_CMOS_THIS s.reg[REG_MIN] = val_bcd;
-
- // update hours
- val_bcd =
- ((time_calendar->tm_hour / 10) << 4) |
- (time_calendar->tm_hour % 10);
- BX_CMOS_THIS s.reg[REG_HOUR] = val_bcd;
-
- // update day of the week
- day = time_calendar->tm_wday + 1; // 0..6 to 1..7
- BX_CMOS_THIS s.reg[REG_WEEK_DAY] = ((day / 10) << 4) | (day % 10);
-
- // update day of the month
- day = time_calendar->tm_mday;
- BX_CMOS_THIS s.reg[REG_MONTH_DAY] = ((day / 10) << 4) | (day % 10);
-
- // update month
- month = time_calendar->tm_mon + 1;
- BX_CMOS_THIS s.reg[REG_MONTH] = ((month / 10) << 4) | (month % 10);
-
- // update year
- year = time_calendar->tm_year % 100;
- BX_CMOS_THIS s.reg[REG_YEAR] = ((year / 10) << 4) | (year % 10);
-
- // update century
- century = (time_calendar->tm_year / 100) + 19;
- BX_CMOS_THIS s.reg[REG_IBM_CENTURY_BYTE] =
- ((century / 10) << 4) | (century % 10);
-
- // Raul Hudea pointed out that some bioses also use reg 0x37 for the
- // century byte. Tony Heller says this is critical in getting WinXP to run.
- BX_CMOS_THIS s.reg[REG_IBM_PS2_CENTURY_BYTE] =
- BX_CMOS_THIS s.reg[REG_IBM_CENTURY_BYTE];
-}
-
- void
-bx_cmos_c::update_timeval()
-{
- struct tm time_calendar;
- Bit8u val_bin;
-
- // update seconds
- val_bin =
- ((BX_CMOS_THIS s.reg[REG_SEC] >> 4) * 10) +
- (BX_CMOS_THIS s.reg[REG_SEC] & 0x0f);
- time_calendar.tm_sec = val_bin;
-
- // update minutes
- val_bin =
- ((BX_CMOS_THIS s.reg[REG_MIN] >> 4) * 10) +
- (BX_CMOS_THIS s.reg[REG_MIN] & 0x0f);
- time_calendar.tm_min = val_bin;
-
- // update hours
- val_bin =
- ((BX_CMOS_THIS s.reg[REG_HOUR] >> 4) * 10) +
- (BX_CMOS_THIS s.reg[REG_HOUR] & 0x0f);
- time_calendar.tm_hour = val_bin;
-
- // update day of the month
- val_bin =
- ((BX_CMOS_THIS s.reg[REG_MONTH_DAY] >> 4) * 10) +
- (BX_CMOS_THIS s.reg[REG_MONTH_DAY] & 0x0f);
- time_calendar.tm_mday = val_bin;
-
- // update month
- val_bin =
- ((BX_CMOS_THIS s.reg[REG_MONTH] >> 4) * 10) +
- (BX_CMOS_THIS s.reg[REG_MONTH] & 0x0f);
- time_calendar.tm_mon = val_bin - 1;
-
- // update year
- val_bin =
- ((BX_CMOS_THIS s.reg[REG_IBM_CENTURY_BYTE] >> 4) * 10) +
- (BX_CMOS_THIS s.reg[REG_IBM_CENTURY_BYTE] & 0x0f);
- val_bin = (val_bin - 19) * 100;
- val_bin +=
- (((BX_CMOS_THIS s.reg[REG_YEAR] >> 4) * 10) +
- (BX_CMOS_THIS s.reg[REG_YEAR] & 0x0f));
- time_calendar.tm_year = val_bin;
-
- BX_CMOS_THIS s.timeval = mktime(& time_calendar);
-}
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: cmos.h,v 1.9 2003/01/04 00:02:07 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-
-
-
-#if BX_USE_CMOS_SMF
-# define BX_CMOS_SMF static
-# define BX_CMOS_THIS theCmosDevice->
-#else
-# define BX_CMOS_SMF
-# define BX_CMOS_THIS this->
-#endif
-
-
-class bx_cmos_c : public bx_cmos_stub_c {
-public:
- bx_cmos_c(void);
- ~bx_cmos_c(void);
-
- virtual void init(void);
- virtual void checksum_cmos(void);
- virtual void reset(unsigned type);
-
- virtual Bit32u get_reg(unsigned reg) {
- return s.reg[reg];
- }
- virtual void set_reg(unsigned reg, Bit32u val) {
- s.reg[reg] = val;
- }
- virtual time_t get_timeval() {
- return s.timeval;
- }
-
- struct {
- int periodic_timer_index;
- Bit32u periodic_interval_usec;
- int one_second_timer_index;
- int uip_timer_index;
- time_t timeval;
- Bit8u cmos_mem_address;
- bx_bool timeval_change;
-
- Bit8u reg[BX_NUM_CMOS_REGS];
- } s; // state information
-
-private:
- static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len);
- static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len);
-#if !BX_USE_CMOS_SMF
- Bit32u read(Bit32u address, unsigned io_len);
- void write(Bit32u address, Bit32u value, unsigned len);
-#endif
-
-public:
- static void periodic_timer_handler(void *);
- static void one_second_timer_handler(void *);
- static void uip_timer_handler(void *);
- BX_CMOS_SMF void periodic_timer(void);
- BX_CMOS_SMF void one_second_timer(void);
- BX_CMOS_SMF void uip_timer(void);
-private:
- BX_CMOS_SMF void update_clock(void);
- BX_CMOS_SMF void update_timeval(void);
- BX_CMOS_SMF void CRA_change(void);
- };
+++ /dev/null
-/*
- * Main cpu loop for handling I/O requests coming from a virtual machine
- * Copyright © 2004, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU Lesser General Public License,
- * version 2.1, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include "bochs.h"
-#include <cpu/cpu.h>
-#ifdef BX_USE_VMX
-#include <sys/ioctl.h>
-/* According to POSIX 1003.1-2001 */
-#include <sys/select.h>
-
-/* According to earlier standards */
-#include <sys/time.h>
-#include <sys/types.h>
-#include <unistd.h>
-#include <values.h>
-#endif
-
-#define LOG_THIS BX_CPU_THIS_PTR
-
-#ifdef BX_USE_VMX
-
-//the evtchn fd for polling
-int evtchn_fd = -1;
-//the evtchn port for polling the notification, should be inputed as bochs's parameter
-u16 ioreq_port = 0;
-
-void *shared_page = NULL;
-
-//some functions to handle the io req packet
-
-//get the ioreq packets from share mem
-ioreq_t* bx_cpu_c::__get_ioreq(void)
-{
- ioreq_t *req;
- req = &((vcpu_iodata_t *) shared_page)->vp_ioreq;
- if (req->state == STATE_IOREQ_READY) {
- req->state = STATE_IOREQ_INPROCESS;
- } else {
- BX_INFO(("False I/O request ... in-service already: %lx, pvalid: %lx,port: %lx, data: %lx, count: %lx, size: %lx\n", req->state, req->pdata_valid, req->addr, req->u.data, req->count, req->size));
- req = NULL;
- }
-
- return req;
-}
-
-//use poll to get the port notification
-//ioreq_vec--out,the
-//retval--the number of ioreq packet
-ioreq_t* bx_cpu_c::get_ioreq(void)
-{
- ioreq_t *req;
- int rc;
- u16 buf[2];
- rc = read(evtchn_fd, buf, 2);
- if (rc == 2 && buf[0] == ioreq_port){//got only one matched 16bit port index
- // unmask the wanted port again
- write(evtchn_fd, &ioreq_port, 2);
-
- //get the io packet from shared memory
- return __get_ioreq();
- }
-
- //read error or read nothing
- return NULL;
-}
-
-//send the ioreq to device model
-void bx_cpu_c::dispatch_ioreq(ioreq_t *req)
-{
- int ret, i;
- int sign;
-
- sign = (req->df) ? -1 : 1;
-
- if ((!req->pdata_valid) && (req->dir == IOREQ_WRITE)) {
- if (req->size != 4) {
- // Bochs expects higher bits to be 0
- req->u.data &= (1UL << (8 * req->size))-1;
- }
- }
- if (req->port_mm == 0){//port io
- if(req->dir == IOREQ_READ){//read
- //BX_INFO(("pio: <READ>addr:%llx, value:%llx, size: %llx, count: %llx\n", req->addr, req->u.data, req->size, req->count));
-
- if (!req->pdata_valid)
- req->u.data = BX_INP(req->addr, req->size);
- else {
- unsigned long tmp;
-
- for (i = 0; i < req->count; i++) {
- tmp = BX_INP(req->addr, req->size);
- BX_MEM_WRITE_PHYSICAL((dma_addr_t) req->u.pdata + (sign * i * req->size),
- req->size, &tmp);
- }
- }
- } else if(req->dir == IOREQ_WRITE) {
- //BX_INFO(("pio: <WRITE>addr:%llx, value:%llx, size: %llx, count: %llx\n", req->addr, req->u.data, req->size, req->count));
-
- if (!req->pdata_valid) {
- BX_OUTP(req->addr, (dma_addr_t) req->u.data, req->size);
- } else {
- for (i = 0; i < req->count; i++) {
- unsigned long tmp;
-
- BX_MEM_READ_PHYSICAL((dma_addr_t) req->u.pdata + (sign * i * req->size), req->size,
- &tmp);
- BX_OUTP(req->addr, (dma_addr_t) tmp, req->size);
- }
- }
-
- }
- } else if (req->port_mm == 1){//memory map io
- if (!req->pdata_valid) {
- if(req->dir == IOREQ_READ){//read
- //BX_INFO(("mmio[value]: <READ> addr:%llx, value:%llx, size: %llx, count: %llx\n", req->addr, req->u.data, req->size, req->count));
- for (i = 0; i < req->count; i++) {
- BX_MEM_READ_PHYSICAL(req->addr + (sign * i * req->size), req->size, &req->u.data);
- }
- } else if(req->dir == IOREQ_WRITE) {//write
- //BX_INFO(("mmio[value]: <WRITE> addr:%llx, value:%llx, size: %llx, count: %llx\n", req->addr, req->u.data, req->size, req->count));
- for (i = 0; i < req->count; i++) {
- BX_MEM_WRITE_PHYSICAL(req->addr + (sign * i * req->size), req->size, &req->u.data);
- }
- }
- } else {
- //handle movs
- unsigned long tmp;
- if (req->dir == IOREQ_READ) {
- //BX_INFO(("mmio[pdata]: <READ>addr:%llx, pdata:%llx, size: %x, count: %x\n", req->addr, req->u.pdata, req->size, req->count));
- for (i = 0; i < req->count; i++) {
- BX_MEM_READ_PHYSICAL(req->addr + (sign * i * req->size), req->size, &tmp);
- BX_MEM_WRITE_PHYSICAL((dma_addr_t) req->u.pdata + (sign * i * req->size), req->size, &tmp);
- }
- } else if (req->dir == IOREQ_WRITE) {
- //BX_INFO(("mmio[pdata]: <WRITE>addr:%llx, pdata:%llx, size: %x, count: %x\n", req->addr, req->u.pdata, req->size, req->count));
- for (i = 0; i < req->count; i++) {
- BX_MEM_READ_PHYSICAL((dma_addr_t)req->u.pdata + (sign * i * req->size), req->size, &tmp);
- BX_MEM_WRITE_PHYSICAL(req->addr + (sign * i * req->size), req->size, &tmp);
- }
- }
- }
- }
-
- /* No state change if state = STATE_IORESP_HOOK */
- if (req->state == STATE_IOREQ_INPROCESS)
- req->state = STATE_IORESP_READY;
-
- send_event = 1;
-}
-
-void
-bx_cpu_c::handle_ioreq(void)
-{
- ioreq_t *req = get_ioreq();
- if (req)
- dispatch_ioreq(req);
-}
-
-void
-bx_cpu_c::timer_handler(void)
-{
- handle_ioreq();
-}
-
-#endif
-
-#define rdtscl(low) \
- __asm__ __volatile__("rdtsc" : "=a" (low) : : "edx")
-
-void
-bx_cpu_c::cpu_loop(int max_instr_count)
-{
- Bit8u vector;
- fd_set rfds;
- unsigned long stime_usec;
- struct timeval tv;
- int retval;
-
- /* Watch stdin (fd 0) to see when it has input. */
- FD_ZERO(&rfds);
-
- while (1) {
- static unsigned long long t1 = 0;
- unsigned long long t2;
-
- /* Wait up to one seconds. */
- tv.tv_sec = 0;
- tv.tv_usec = 100000;
- FD_SET(evtchn_fd, &rfds);
-
- send_event = 0;
-
- if (t1 == 0) // the first time
- rdtscll(t1);
-
- retval = select(evtchn_fd+1, &rfds, NULL, NULL, &tv);
- if (retval == -1) {
- perror("select");
- return;
- }
-
- rdtscll(t2);
-
-#if __WORDSIZE == 32
-#define ULONGLONG_MAX 0xffffffffffffffffULL
-#else
-#define ULONGLONG_MAX ULONG_MAX
-#endif
-
- if (t2 <= t1)
- BX_TICKN((t2 + ULONGLONG_MAX - t1) / tsc_per_bx_tick);
- else
- BX_TICKN((t2 - t1) / tsc_per_bx_tick);
- t1 = t2;
-
- timer_handler();
- if (BX_CPU_INTR) {
-#if BX_SUPPORT_APIC
- if (BX_CPU_THIS_PTR local_apic.INTR)
- vector = BX_CPU_THIS_PTR local_apic.acknowledge_int ();
- else
- vector = DEV_pic_iac(); // may set INTR with next interrupt
-#else
- // if no local APIC, always acknowledge the PIC.
- vector = DEV_pic_iac(); // may set INTR with next interrupt
-#endif
- interrupt(vector);
- }
- /* we check DMA after interrupt check*/
- while(BX_HRQ){
- DEV_dma_raise_hlda();
- }
-
- if (send_event) {
- int ret;
- ret = xc_evtchn_send(xc_handle, ioreq_port);
- if (ret == -1) {
- BX_ERROR(("evtchn_send failed on port: %d\n", ioreq_port));
- }
- }
- }
-}
-
-#ifdef __i386__
-static __inline__ void set_bit(long nr, volatile void *addr)
-{
- __asm__ __volatile__( "lock ; "
- "btsl %1,%0"
- :"=m" ((*(volatile long *)addr))
- :"Ir" (nr));
-
- return;
-}
-#else
-/* XXX: clean for IPF */
-static __inline__ void set_bit(long nr, volatile void *addr)
-{
- __asm__ __volatile__( "lock ; "
- "btsq %1,%0"
- :"=m" ((*(volatile long *)addr))
- :"Ir" (nr));
-
- return;
-}
-#endif
-
-void
-bx_cpu_c::interrupt(Bit8u vector)
-{
- unsigned long *intr, tscl;
- int ret;
-
- // Send a message on the event channel. Add the vector to the shared mem
- // page.
-
- rdtscl(tscl);
- BX_DEBUG(("%lx: injecting vector: %x\n", tscl, vector));
- intr = &(((vcpu_iodata_t *) shared_page)->vp_intr[0]);
- set_bit(vector, intr);
-
- send_event = 1;
-}
-
-void
-bx_cpu_c::init(bx_mem_c*)
-{
-#ifdef BX_USE_VMX
- if (evtchn_fd != -1)//the evtchn has been opened by another cpu object
- return;
-
- //use nonblock reading not polling, may change in future.
- evtchn_fd = open("/dev/xen/evtchn", O_RDWR|O_NONBLOCK);
- if (evtchn_fd == -1) {
- perror("open");
- return;
- }
-
- BX_INFO(("listening to port: %d\n", ioreq_port));
- /*unmask the wanted port -- bind*/
- if (ioctl(evtchn_fd, ('E'<<8)|2, ioreq_port) == -1) {
- perror("ioctl");
- return;
- }
-
-#if 0
- //register the reading evtchn function as timer
- bx_pc_system.register_timer(this, timer_handler, 1000,//1000 us, may change
- 1,//continuous timer
- 1,//active
- "cpu reading evtchn handler");
-#endif
-
-#endif
-}
-
-void
-bx_cpu_c::reset(unsigned)
-{
-}
-
-void
-bx_cpu_c::atexit()
-{
-}
-
-void
-bx_cpu_c::set_INTR(unsigned value)
-{
- BX_CPU_THIS_PTR INTR = value;
-}
-
-void
-bx_cpu_c::pagingA20Changed()
-{
-}
-
-bx_cpu_c::bx_cpu_c()
-{
-}
-
-bx_cpu_c::~bx_cpu_c()
-{
-}
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: crc32.cc,v 1.4 2001/10/03 13:10:38 bdenney Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-/* CRC-32 calculator
- * Adapted from http://www.createwindow.org/programming/crc32/
- */
-
-#include "crc32.h"
-
-CRC_Generator::CRC_Generator() {
- init();
-}
-
-void CRC_Generator::init(void) {
- Bit32u POLYNOMIAL = 0x04c11db7;
- int i;
-
- for(i = 0; i<0xFF; i++) {
- int j;
- crc32_table[i]=reflect(i,8) << 24;
- for(j=0; j<8; j++)
- crc32_table[i] = (crc32_table[i]<<1)^(crc32_table[i] & (1<<31) ? POLYNOMIAL : 0);
- crc32_table[i] = reflect(crc32_table[i], 32);
- }
-}
-
-Bit32u CRC_Generator::reflect(Bit32u ref, Bit8u ch) {
- Bit32u value(0);
- int i;
-
- for(i=1; i<(ch+1); i++) {
- if(ref & 1)
- value |= 1 << (ch-i);
- ref >>= 1;
- }
- return value;
-}
-
-Bit32u CRC_Generator::get_CRC(Bit8u * buf, Bit32u buflen) {
- Bit32u ulCRC(0xFFFFFFFF);
- Bit32u len(buflen);
- Bit8u * buffer=(Bit8u *) buf;
-
- while(len--)
- ulCRC=(ulCRC>>8)^crc32_table[(ulCRC & 0xFF)^*buffer++];
- return ulCRC ^ 0xFFFFFFFF;
-}
-
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: crc32.h,v 1.3 2001/10/03 13:10:38 bdenney Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-/* CRC-32 calculator
- * Adapted from http://www.createwindow.org/programming/crc32/
- */
-
-#ifndef _CRC_32_H_
-#define _CRC_32_H_
-
-#include "bochs.h"
-
-class CRC_Generator {
-private:
- Bit32u crc32_table[256];
- Bit32u reflect(Bit32u ref, Bit8u ch);
-public:
- void init(void);
- CRC_Generator();
- Bit32u get_CRC(Bit8u * buf, Bit32u buflen);
-};
-
-#endif //_CRC_32_H_
-
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: devices.cc,v 1.58 2003/12/26 13:53:39 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-#include "bochs.h"
-#define LOG_THIS bx_devices.
-
-
-
-/* main memory size (in Kbytes)
- * subtract 1k for extended BIOS area
- * report only base memory, not extended mem
- */
-#define BASE_MEMORY_IN_K 640
-
-
-bx_devices_c bx_devices;
-
-
-
-
-// constructor for bx_devices_c
-bx_devices_c::bx_devices_c(void)
-{
- put("DEV");
- settype(DEVLOG);
-
-#if BX_PCI_SUPPORT
- pluginPciBridge = &stubPci;
- pluginPci2IsaBridge = NULL;
-#if BX_PCI_VGA_SUPPORT
- pluginPciVgaAdapter = NULL;
-#endif
-#if BX_PCI_USB_SUPPORT
- pluginPciUSBAdapter = NULL;
-#endif
-#endif
- pit = NULL;
- pluginKeyboard = &stubKeyboard;
- pluginDmaDevice = &stubDma;
- pluginFloppyDevice = &stubFloppy;
- pluginBiosDevice = NULL;
- pluginCmosDevice = &stubCmos;
- pluginSerialDevice = NULL;
- pluginParallelDevice = NULL;
- pluginUnmapped = NULL;
- pluginVgaDevice = &stubVga;
- pluginPicDevice = &stubPic;
- pluginHardDrive = &stubHardDrive;
- pluginSB16Device = NULL;
- pluginNE2kDevice =&stubNE2k;
- pluginExtFpuIrq = NULL;
- pluginGameport = NULL;
- g2h = NULL;
-#if BX_IODEBUG_SUPPORT
- iodebug = NULL;
-#endif
-}
-
-
-bx_devices_c::~bx_devices_c(void)
-{
- // nothing needed for now
- BX_DEBUG(("Exit."));
- timer_handle = BX_NULL_TIMER_HANDLE;
-}
-
-
- void
-bx_devices_c::init(BX_MEM_C *newmem)
-{
- unsigned i;
-
- BX_DEBUG(("Init $Id: devices.cc,v 1.58 2003/12/26 13:53:39 vruppert Exp $"));
- mem = newmem;
-
- /* no read / write handlers defined */
- num_read_handles = 0;
- num_write_handles = 0;
-
- /* set unused elements to appropriate values */
- for (i=0; i < BX_MAX_IO_DEVICES; i++) {
- io_read_handler[i].funct = NULL;
- io_write_handler[i].funct = NULL;
- }
-
- /* set no-default handlers, will be overwritten by the real default handler */
- io_read_handler[BX_DEFAULT_IO_DEVICE].handler_name = "Default";
- io_read_handler[BX_DEFAULT_IO_DEVICE].funct = &default_read_handler;
- io_read_handler[BX_DEFAULT_IO_DEVICE].this_ptr = NULL;
- io_read_handler[BX_DEFAULT_IO_DEVICE].mask = 7;
- io_write_handler[BX_DEFAULT_IO_DEVICE].handler_name = "Default";
- io_write_handler[BX_DEFAULT_IO_DEVICE].funct = &default_write_handler;
- io_write_handler[BX_DEFAULT_IO_DEVICE].this_ptr = NULL;
- io_write_handler[BX_DEFAULT_IO_DEVICE].mask = 7;
-
- /* set handlers to the default one */
- for (i=0; i < 0x10000; i++) {
- read_handler_id[i] = BX_DEFAULT_IO_DEVICE;
- write_handler_id[i] = BX_DEFAULT_IO_DEVICE;
- }
-
- for (i=0; i < BX_MAX_IRQS; i++) {
- irq_handler_name[i] = NULL;
- }
-
- // BBD: At present, the only difference between "core" and "optional"
- // plugins is that initialization and reset of optional plugins is handled
- // by the plugin device list (). Init and reset of core plugins is done
- // "by hand" in this file. Basically, we're using core plugins when we
- // want to control the init order.
- //
- // CB: UNMAPPED and BIOSDEV should maybe be optional
- PLUG_load_plugin(unmapped, PLUGTYPE_CORE);
- PLUG_load_plugin(biosdev, PLUGTYPE_CORE);
- PLUG_load_plugin(cmos, PLUGTYPE_CORE);
- PLUG_load_plugin(dma, PLUGTYPE_CORE);
- PLUG_load_plugin(pic, PLUGTYPE_CORE);
- PLUG_load_plugin(vga, PLUGTYPE_CORE);
- PLUG_load_plugin(floppy, PLUGTYPE_CORE);
- PLUG_load_plugin(harddrv, PLUGTYPE_OPTIONAL);
- PLUG_load_plugin(keyboard, PLUGTYPE_OPTIONAL);
- if (is_serial_enabled ())
- PLUG_load_plugin(serial, PLUGTYPE_OPTIONAL);
- if (is_parallel_enabled ())
- PLUG_load_plugin(parallel, PLUGTYPE_OPTIONAL);
- PLUG_load_plugin(extfpuirq, PLUGTYPE_OPTIONAL);
-#if BX_SUPPORT_GAME
- PLUG_load_plugin(gameport, PLUGTYPE_OPTIONAL);
-#endif
-
- // Start with registering the default (unmapped) handler
- pluginUnmapped->init ();
-
- // PCI logic (i440FX)
- if (bx_options.Oi440FXSupport->get ()) {
-#if BX_PCI_SUPPORT
- PLUG_load_plugin(pci, PLUGTYPE_OPTIONAL);
- PLUG_load_plugin(pci2isa, PLUGTYPE_OPTIONAL);
-#if BX_PCI_VGA_SUPPORT
- PLUG_load_plugin(pcivga, PLUGTYPE_OPTIONAL);
-#endif
-#if BX_PCI_USB_SUPPORT
- PLUG_load_plugin(pciusb, PLUGTYPE_OPTIONAL);
-#endif
-#else
- BX_ERROR(("Bochs is not compiled with PCI support"));
-#endif
- }
-
-#if BX_SUPPORT_APIC
- // I/O APIC 82093AA
- ioapic = & bx_ioapic;
- ioapic->init ();
-#endif
-
- // BIOS log
- pluginBiosDevice->init ();
-
- // CMOS RAM & RTC
- pluginCmosDevice->init ();
-
- /*--- 8237 DMA ---*/
- pluginDmaDevice->init();
-
- //--- FLOPPY ---
- pluginFloppyDevice->init();
-
- //--- SOUND ---
- if (bx_options.sb16.Opresent->get ()) {
-#if BX_SUPPORT_SB16
- PLUG_load_plugin(sb16, PLUGTYPE_OPTIONAL);
-#else
- BX_ERROR(("Bochs is not compiled with SB16 support"));
-#endif
- }
-
- /*--- VGA adapter ---*/
- pluginVgaDevice->init ();
-
- /*--- 8259A PIC ---*/
- pluginPicDevice->init();
-
- /*--- 8254 PIT ---*/
- pit = & bx_pit;
- pit->init();
-
- bx_virt_timer.init();
-
- bx_slowdown_timer.init();
-
-#if BX_IODEBUG_SUPPORT
- iodebug = &bx_iodebug;
- iodebug->init();
-#endif
-
- // NE2000 NIC
- if (bx_options.ne2k.Opresent->get ()) {
-#if BX_NE2K_SUPPORT
- PLUG_load_plugin(ne2k, PLUGTYPE_OPTIONAL);
-#else
- BX_ERROR(("Bochs is not compiled with NE2K support"));
-#endif
- }
-
-#if 0
- // Guest to Host interface. Used with special guest drivers
- // which move data to/from the host environment.
- g2h = &bx_g2h;
- g2h->init();
-#endif
-
- // system hardware
- register_io_read_handler( this,
- &read_handler,
- 0x0092,
- "Port 92h System Control", 1 );
- register_io_write_handler(this,
- &write_handler,
- 0x0092,
- "Port 92h System Control", 1 );
-
- // misc. CMOS
- Bit32u extended_memory_in_k = mem->get_memory_in_k() > 1024 ? (mem->get_memory_in_k() - 1024) : 0;
- if (extended_memory_in_k > 0xffff) extended_memory_in_k = 0xffff;
-
- DEV_cmos_set_reg(0x15, (Bit8u) BASE_MEMORY_IN_K);
- DEV_cmos_set_reg(0x16, (Bit8u) (BASE_MEMORY_IN_K >> 8));
- DEV_cmos_set_reg(0x17, (Bit8u) (extended_memory_in_k & 0xff) );
- DEV_cmos_set_reg(0x18, (Bit8u) ((extended_memory_in_k >> 8) & 0xff) );
- DEV_cmos_set_reg(0x30, (Bit8u) (extended_memory_in_k & 0xff) );
- DEV_cmos_set_reg(0x31, (Bit8u) ((extended_memory_in_k >> 8) & 0xff) );
-
- Bit32u extended_memory_in_64k = mem->get_memory_in_k() > 16384 ? (mem->get_memory_in_k() - 16384) / 64 : 0;
- if (extended_memory_in_64k > 0xffff) extended_memory_in_64k = 0xffff;
-
- DEV_cmos_set_reg(0x34, (Bit8u) (extended_memory_in_64k & 0xff) );
- DEV_cmos_set_reg(0x35, (Bit8u) ((extended_memory_in_64k >> 8) & 0xff) );
-
- if (timer_handle != BX_NULL_TIMER_HANDLE) {
- timer_handle = bx_pc_system.register_timer( this, timer_handler,
- (unsigned) BX_IODEV_HANDLER_PERIOD, 1, 1, "devices.cc");
- }
-
- // Clear fields for bulk IO acceleration transfers.
- bulkIOHostAddr = 0;
- bulkIOQuantumsRequested = 0;
- bulkIOQuantumsTransferred = 0;
-
- bx_init_plugins();
-
- /* now perform checksum of CMOS memory */
- DEV_cmos_checksum();
-}
-
-
- void
-bx_devices_c::reset(unsigned type)
-{
- pluginUnmapped->reset(type);
-#if BX_PCI_SUPPORT
- if (bx_options.Oi440FXSupport->get ()) {
- pluginPciBridge->reset(type);
- pluginPci2IsaBridge->reset(type);
-#if BX_PCI_VGA_SUPPORT
- pluginPciVgaAdapter->reset(type);
-#endif
-#if BX_PCI_USB_SUPPORT
- pluginPciUSBAdapter->reset(type);
-#endif
- }
-#endif
-#if BX_SUPPORT_IOAPIC
- ioapic->reset (type);
-#endif
- pluginBiosDevice->reset(type);
- pluginCmosDevice->reset(type);
- pluginDmaDevice->reset(type);
- pluginFloppyDevice->reset(type);
-#if BX_SUPPORT_SB16
- if (pluginSB16Device) pluginSB16Device->reset(type);
-#endif
- pluginVgaDevice->reset(type);
- pluginPicDevice->reset(type);
- pit->reset(type);
- bx_slowdown_timer.reset(type);
-#if BX_IODEBUG_SUPPORT
- iodebug->reset(type);
-#endif
-#if BX_NE2K_SUPPORT
- if (pluginNE2kDevice) pluginNE2kDevice->reset(type);
-#endif
-
- bx_reset_plugins(type);
-}
-
-
- Bit32u
-bx_devices_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len)
-{
-#if !BX_USE_DEV_SMF
- bx_devices_c *class_ptr = (bx_devices_c *) this_ptr;
-
- return( class_ptr->port92_read(address, io_len) );
-}
-
-
- Bit32u
-bx_devices_c::port92_read(Bit32u address, unsigned io_len)
-{
-#else
- UNUSED(this_ptr);
-#endif // !BX_USE_DEV_SMF
-
- BX_DEBUG(("port92h read partially supported!!!"));
- BX_DEBUG((" returning %02x", (unsigned) (BX_GET_ENABLE_A20() << 1)));
- return(BX_GET_ENABLE_A20() << 1);
-}
-
-
- void
-bx_devices_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len)
-{
-#if !BX_USE_DEV_SMF
- bx_devices_c *class_ptr = (bx_devices_c *) this_ptr;
-
- class_ptr->port92_write(address, value, io_len);
-}
-
- void
-bx_devices_c::port92_write(Bit32u address, Bit32u value, unsigned io_len)
-{
-#else
- UNUSED(this_ptr);
-#endif // !BX_USE_DEV_SMF
- bx_bool bx_cpu_reset;
-
- BX_DEBUG(("port92h write of %02x partially supported!!!",
- (unsigned) value));
- BX_DEBUG(("A20: set_enable_a20() called"));
- BX_SET_ENABLE_A20( (value & 0x02) >> 1 );
- BX_DEBUG(("A20: now %u", (unsigned) BX_GET_ENABLE_A20()));
- bx_cpu_reset = (value & 0x01); /* high speed reset */
- if (bx_cpu_reset) {
- BX_PANIC(("PORT 92h write: CPU reset requested!"));
- }
-}
-
-
-// This defines a no-default read handler,
-// so Bochs does not segfault if unmapped is not loaded
- Bit32u
-bx_devices_c::default_read_handler(void *this_ptr, Bit32u address, unsigned io_len)
-{
- UNUSED(this_ptr);
- BX_PANIC(("No default io-read handler found for 0x%04x/%d. Unmapped io-device not loaded ?", address, io_len));
- return 0xffffffff;
-}
-
-// This defines a no-default write handler,
-// so Bochs does not segfault if unmapped is not loaded
- void
-bx_devices_c::default_write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len)
-{
- UNUSED(this_ptr);
- BX_PANIC(("No default io-write handler found for 0x%04x/%d. Unmapped io-device not loaded ?", address, io_len));
-}
-
- void
-bx_devices_c::timer_handler(void *this_ptr)
-{
- bx_devices_c *class_ptr = (bx_devices_c *) this_ptr;
-
- class_ptr->timer();
-}
-
- void
-bx_devices_c::timer()
-{
-#if (BX_USE_NEW_PIT==0)
- if ( pit->periodic( BX_IODEV_HANDLER_PERIOD ) ) {
- // This is a hack to make the IRQ0 work
- DEV_pic_lower_irq(0);
- DEV_pic_raise_irq(0);
- }
-#endif
-
-
- // separate calls to bx_gui->handle_events from the keyboard code.
- {
- static int multiple=0;
- if ( ++multiple==10)
- {
- multiple=0;
- SIM->periodic ();
- if (!BX_CPU(0)->kill_bochs_request)
- bx_gui->handle_events();
- }
- }
-
-// KPL Removed lapic periodic timer registration here.
-}
-
-
- bx_bool
-bx_devices_c::register_irq(unsigned irq, const char *name)
-{
- if (irq >= BX_MAX_IRQS) {
- BX_PANIC(("IO device %s registered with IRQ=%d above %u",
- name, irq, (unsigned) BX_MAX_IRQS-1));
- return false;
- }
- if (irq_handler_name[irq]) {
- BX_PANIC(("IRQ %u conflict, %s with %s", irq,
- irq_handler_name[irq], name));
- return false;
- }
- irq_handler_name[irq] = name;
- return true;
-}
-
- bx_bool
-bx_devices_c::unregister_irq(unsigned irq, const char *name)
-{
- if (irq >= BX_MAX_IRQS) {
- BX_PANIC(("IO device %s tried to unregister IRQ %d above %u",
- name, irq, (unsigned) BX_MAX_IRQS-1));
- return false;
- }
-
- if (!irq_handler_name[irq]) {
- BX_INFO(("IO device %s tried to unregister IRQ %d, not registered",
- name, irq));
- return false;
- }
-
- if (strcmp(irq_handler_name[irq], name)) {
- BX_INFO(("IRQ %u not registered to %s but to %s", irq,
- name, irq_handler_name[irq]));
- return false;
- }
- irq_handler_name[irq] = NULL;
- return true;
-}
-
- bx_bool
-bx_devices_c::register_io_read_handler( void *this_ptr, bx_read_handler_t f,
- Bit32u addr, const char *name, Bit8u mask )
-{
- unsigned handle;
-
- addr &= 0x0000ffff;
-
- /* first find existing handle for function or create new one */
- for (handle=0; handle < num_read_handles; handle++) {
- if ((io_read_handler[handle].funct == f) &&
- (io_read_handler[handle].mask == mask)) break;
- }
-
- if (handle >= num_read_handles) {
- /* no existing handle found, create new one */
- if (num_read_handles >= BX_DEFAULT_IO_DEVICE) {
- BX_INFO(("too many IO devices installed."));
- BX_PANIC((" try increasing BX_MAX_IO_DEVICES"));
- }
- num_read_handles++;
- io_read_handler[handle].funct = f;
- io_read_handler[handle].this_ptr = this_ptr;
- io_read_handler[handle].handler_name = name;
- io_read_handler[handle].mask = mask;
- }
-
- /* change table to reflect new handler id for that address */
- if (read_handler_id[addr] < BX_DEFAULT_IO_DEVICE) {
- // another handler is already registered for that address
- BX_ERROR(("IO device address conflict(read) at IO address %Xh",
- (unsigned) addr));
- BX_ERROR((" conflicting devices: %s & %s",
- io_read_handler[handle].handler_name, io_read_handler[read_handler_id[addr]].handler_name));
- return false; // address not available, return false.
- }
- read_handler_id[addr] = handle;
- return true; // address mapped successfully
-}
-
-
-
- bx_bool
-bx_devices_c::register_io_write_handler( void *this_ptr, bx_write_handler_t f,
- Bit32u addr, const char *name, Bit8u mask )
-{
- unsigned handle;
-
- addr &= 0x0000ffff;
-
- /* first find existing handle for function or create new one */
- for (handle=0; handle < num_write_handles; handle++) {
- if ((io_write_handler[handle].funct == f) &&
- (io_write_handler[handle].mask == mask)) break;
- }
-
- if (handle >= num_write_handles) {
- /* no existing handle found, create new one */
- if (num_write_handles >= BX_DEFAULT_IO_DEVICE) {
- BX_INFO(("too many IO devices installed."));
- BX_PANIC((" try increasing BX_MAX_IO_DEVICES"));
- }
- num_write_handles++;
- io_write_handler[handle].funct = f;
- io_write_handler[handle].this_ptr = this_ptr;
- io_write_handler[handle].handler_name = name;
- io_write_handler[handle].mask = mask;
- }
-
- /* change table to reflect new handler id for that address */
- if (write_handler_id[addr] < BX_DEFAULT_IO_DEVICE) {
- // another handler is already registered for that address
- BX_ERROR(("IO device address conflict(write) at IO address %Xh",
- (unsigned) addr));
- BX_ERROR((" conflicting devices: %s & %s",
- io_write_handler[handle].handler_name, io_write_handler[write_handler_id[addr]].handler_name));
- return false; //unable to map iodevice.
- }
- write_handler_id[addr] = handle;
- return true; // done!
-}
-
-
-// Registration of default handlers (mainly be the unmapped device)
-// The trick here is to define a handler for the max index, so
-// unregisterd io address will get handled by the default function
-// This will be helpful when we want to unregister io handlers
-
- bx_bool
-bx_devices_c::register_default_io_read_handler( void *this_ptr, bx_read_handler_t f,
- const char *name, Bit8u mask )
-{
- unsigned handle;
-
- /* handle is fixed to the default I/O device */
- handle = BX_DEFAULT_IO_DEVICE;
-
- if (strcmp(io_read_handler[handle].handler_name, "Default")) {
- BX_ERROR(("Default io read handler already registered '%s'",io_read_handler[handle].handler_name));
- return false;
- }
-
- io_read_handler[handle].funct = f;
- io_read_handler[handle].this_ptr = this_ptr;
- io_read_handler[handle].handler_name = name;
- io_read_handler[handle].mask = mask;
-
- return true;
-}
-
-
-
- bx_bool
-bx_devices_c::register_default_io_write_handler( void *this_ptr, bx_write_handler_t f,
- const char *name, Bit8u mask )
-{
- unsigned handle;
-
- /* handle is fixed to the MAX */
- handle = BX_DEFAULT_IO_DEVICE;
-
- if (strcmp(io_write_handler[handle].handler_name, "Default")) {
- BX_ERROR(("Default io write handler already registered '%s'",io_write_handler[handle].handler_name));
- return false;
- }
-
- io_write_handler[handle].funct = f;
- io_write_handler[handle].this_ptr = this_ptr;
- io_write_handler[handle].handler_name = name;
- io_write_handler[handle].mask = mask;
-
- return true;
-}
-
-
-
-/*
- * Read a byte of data from the IO memory address space
- */
-
- Bit32u BX_CPP_AttrRegparmN(2)
-bx_devices_c::inp(Bit16u addr, unsigned io_len)
-{
- Bit8u handle;
- Bit32u ret;
-
- BX_INSTR_INP(addr, io_len);
-
- handle = read_handler_id[addr];
- if ((io_read_handler[handle].funct != NULL) &&
- (io_read_handler[handle].mask & io_len)) {
- ret = (* io_read_handler[handle].funct)(io_read_handler[handle].this_ptr,
- (Bit32u) addr, io_len);
- } else {
- switch (io_len) {
- case 1: ret = 0xff; break;
- case 2: ret = 0xffff; break;
- default: ret = 0xffffffff; break;
- }
- BX_ERROR(("read from port 0x%04x with len %d returns 0x%x", addr, io_len, ret));
- }
- BX_INSTR_INP2(addr, io_len, ret);
- BX_DBG_IO_REPORT(addr, io_len, BX_READ, ret);
-
- return(ret);
-}
-
-
-/*
- * Write a byte of data to the IO memory address space.
- */
-
- void BX_CPP_AttrRegparmN(3)
-bx_devices_c::outp(Bit16u addr, Bit32u value, unsigned io_len)
-{
- Bit8u handle;
-
- BX_INSTR_OUTP(addr, io_len);
- BX_INSTR_OUTP2(addr, io_len, value);
-
- BX_DBG_IO_REPORT(addr, io_len, BX_WRITE, value);
- handle = write_handler_id[addr];
- if ((io_write_handler[handle].funct != NULL) &&
- (io_write_handler[handle].mask & io_len)) {
- (* io_write_handler[handle].funct)(io_write_handler[handle].this_ptr,
- (Bit32u) addr, value, io_len);
- } else {
- BX_ERROR(("write to port 0x%04x with len %d ignored", addr, io_len));
- }
-}
-
-bx_bool bx_devices_c::is_serial_enabled ()
-{
- for (int i=0; i<BX_N_SERIAL_PORTS; i++) {
- if (SIM->get_param_bool (BXP_COMx_ENABLED(i+1))->get())
- return true;
- }
- return false;
-}
-
-bx_bool bx_devices_c::is_usb_enabled ()
-{
- for (int i=0; i<BX_N_USB_HUBS; i++) {
- if (SIM->get_param_bool (BXP_USBx_ENABLED(i+1))->get())
- return true;
- }
- return false;
-}
-
-bx_bool bx_devices_c::is_parallel_enabled ()
-{
- for (int i=0; i<BX_N_PARALLEL_PORTS; i++) {
- if (SIM->get_param_bool (BXP_PARPORTx_ENABLED(i+1))->get())
- return true;
- }
- return false;
-}
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: dma.cc,v 1.30 2003/07/31 15:29:34 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-
-// Define BX_PLUGGABLE in files that can be compiled into plugins. For
-// platforms that require a special tag on exported symbols, BX_PLUGGABLE
-// is used to know when we are exporting symbols and when we are importing.
-#define BX_PLUGGABLE
-
-#include "bochs.h"
-
-#define LOG_THIS theDmaDevice->
-
-#define DMA_MODE_DEMAND 0
-#define DMA_MODE_SINGLE 1
-#define DMA_MODE_BLOCK 2
-#define DMA_MODE_CASCADE 3
-
-bx_dma_c *theDmaDevice = NULL;
-
- int
-libdma_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[])
-{
- theDmaDevice = new bx_dma_c ();
- bx_devices.pluginDmaDevice = theDmaDevice;
- BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theDmaDevice, BX_PLUGIN_DMA);
- return(0); // Success
-}
-
- void
-libdma_LTX_plugin_fini(void)
-{
-}
-
-bx_dma_c::bx_dma_c(void)
-{
- put("DMA");
- settype(DMALOG);
-}
-
-bx_dma_c::~bx_dma_c(void)
-{
- BX_DEBUG(("Exit."));
-}
-
- unsigned
-bx_dma_c::registerDMA8Channel(
- unsigned channel,
- void (* dmaRead)(Bit8u *data_byte),
- void (* dmaWrite)(Bit8u *data_byte),
- const char *name
- )
-{
- if (channel > 3) {
- BX_PANIC(("registerDMA8Channel: invalid channel number(%u).", channel));
- return 0; // Fail.
- }
- if (BX_DMA_THIS s[0].chan[channel].used) {
- BX_PANIC(("registerDMA8Channel: channel(%u) already in use.", channel));
- return 0; // Fail.
- }
- BX_INFO(("channel %u used by %s", channel, name));
- BX_DMA_THIS h[channel].dmaRead8 = dmaRead;
- BX_DMA_THIS h[channel].dmaWrite8 = dmaWrite;
- BX_DMA_THIS s[0].chan[channel].used = 1;
- return 1; // OK.
-}
-
- unsigned
-bx_dma_c::registerDMA16Channel(
- unsigned channel,
- void (* dmaRead)(Bit16u *data_word),
- void (* dmaWrite)(Bit16u *data_word),
- const char *name
- )
-{
- if ((channel < 4) || (channel > 7)) {
- BX_PANIC(("registerDMA16Channel: invalid channel number(%u).", channel));
- return 0; // Fail.
- }
- if (BX_DMA_THIS s[1].chan[channel & 0x03].used) {
- BX_PANIC(("registerDMA16Channel: channel(%u) already in use.", channel));
- return 0; // Fail.
- }
- BX_INFO(("channel %u used by %s", channel, name));
- channel &= 0x03;
- BX_DMA_THIS h[channel].dmaRead16 = dmaRead;
- BX_DMA_THIS h[channel].dmaWrite16 = dmaWrite;
- BX_DMA_THIS s[1].chan[channel].used = 1;
- return 1; // OK.
-}
-
- unsigned
-bx_dma_c::unregisterDMAChannel(unsigned channel)
-{
- bx_bool ma_sl = (channel > 3);
- BX_DMA_THIS s[ma_sl].chan[channel & 0x03].used = 0;
- BX_INFO(("channel %u no longer used", channel));
- return 1;
-}
-
- unsigned
-bx_dma_c::get_TC(void)
-{
- return BX_DMA_THIS TC;
-}
-
-
- void
-bx_dma_c::init(void)
-{
- unsigned c, i, j;
- BX_DEBUG(("Init $Id: dma.cc,v 1.30 2003/07/31 15:29:34 vruppert Exp $"));
-
- /* 8237 DMA controller */
-
- for (i=0; i < 2; i++) {
- for (j=0; j < 4; j++) {
- BX_DMA_THIS s[i].DRQ[j] = 0;
- BX_DMA_THIS s[i].DACK[j] = 0;
- }
- }
- BX_DMA_THIS HLDA = 0;
- BX_DMA_THIS TC = 0;
-
- // 0000..000F
- for (i=0x0000; i<=0x000F; i++) {
- DEV_register_ioread_handler(this, read_handler, i, "DMA controller", 1);
- DEV_register_iowrite_handler(this, write_handler, i, "DMA controller", 3);
- }
-
- // 00081..008F
- for (i=0x0081; i<=0x008F; i++) {
- DEV_register_ioread_handler(this, read_handler, i, "DMA controller", 1);
- DEV_register_iowrite_handler(this, write_handler, i, "DMA controller", 3);
- }
-
- // 000C0..00DE
- for (i=0x00C0; i<=0x00DE; i+=2) {
- DEV_register_ioread_handler(this, read_handler, i, "DMA controller", 1);
- DEV_register_iowrite_handler(this, write_handler, i, "DMA controller", 3);
- }
-
-
- for (i=0; i<2; i++) {
- for (c=0; c<4; c++) {
- BX_DMA_THIS s[i].chan[c].mode.mode_type = 0; // demand mode
- BX_DMA_THIS s[i].chan[c].mode.address_decrement = 0; // address increment
- BX_DMA_THIS s[i].chan[c].mode.autoinit_enable = 0; // autoinit disable
- BX_DMA_THIS s[i].chan[c].mode.transfer_type = 0; // verify
- BX_DMA_THIS s[i].chan[c].base_address = 0;
- BX_DMA_THIS s[i].chan[c].current_address = 0;
- BX_DMA_THIS s[i].chan[c].base_count = 0;
- BX_DMA_THIS s[i].chan[c].current_count = 0;
- BX_DMA_THIS s[i].chan[c].page_reg = 0;
- BX_DMA_THIS s[i].chan[c].used = 0;
- }
- }
- BX_DMA_THIS s[1].chan[0].used = 1; // cascade channel in use
- BX_INFO(("channel 4 used by cascade"));
- bios_init();
-}
-
-/* Remove it when guest fw ready*/
- void
-bx_dma_c::bios_init(void){
- BX_DMA_THIS s[1].mask[0] = 0; // unmask cascade channel
- BX_DMA_THIS s[1].chan[0].mode.mode_type = 3; // cascade mode for channel 4
-}
-
- void
-bx_dma_c::reset(unsigned type)
-{
- reset_controller(0);
- reset_controller(1);
- bios_init();
-}
-
- void
-bx_dma_c::reset_controller(unsigned num)
-{
- BX_DMA_THIS s[num].mask[0] = 1;
- BX_DMA_THIS s[num].mask[1] = 1;
- BX_DMA_THIS s[num].mask[2] = 1;
- BX_DMA_THIS s[num].mask[3] = 1;
- BX_DMA_THIS s[num].command_reg = 0;
- BX_DMA_THIS s[num].status_reg = 0;
- BX_DMA_THIS s[num].request_reg = 0;
- BX_DMA_THIS s[num].temporary_reg = 0;
- BX_DMA_THIS s[num].flip_flop = 0;
-}
-
- // index to find channel from register number (only [0],[1],[2],[6] used)
- Bit8u channelindex[7] = {2, 3, 1, 0, 0, 0, 0};
-
-
- // static IO port read callback handler
- // redirects to non-static class handler to avoid virtual functions
-
- Bit32u
-bx_dma_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len)
-{
-#if !BX_USE_DMA_SMF
- bx_dma_c *class_ptr = (bx_dma_c *) this_ptr;
-
- return( class_ptr->read(address, io_len) );
-}
-
- /* 8237 DMA controller */
- Bit32u BX_CPP_AttrRegparmN(2)
-bx_dma_c::read( Bit32u address, unsigned io_len)
-{
-#else
- UNUSED(this_ptr);
-#endif // !BX_USE_DMA_SMF
-
- Bit8u retval;
- Bit8u channel;
- bx_bool ma_sl;
-
- BX_DEBUG(("read addr=%04x", (unsigned) address));
-
-#if BX_DMA_FLOPPY_IO < 1
- /* if we're not supporting DMA/floppy IO just return a bogus value */
- return(0xff);
-#endif
-
- switch (address) {
- case 0x00: /* DMA-1 current address, channel 0 */
- case 0x02: /* DMA-1 current address, channel 1 */
- case 0x04: /* DMA-1 current address, channel 2 */
- case 0x06: /* DMA-1 current address, channel 3 */
- case 0xc0: /* DMA-2 current address, channel 0 */
- case 0xc4: /* DMA-2 current address, channel 1 */
- case 0xc8: /* DMA-2 current address, channel 2 */
- case 0xcc: /* DMA-2 current address, channel 3 */
- ma_sl = (address >= 0xc0);
- channel = (address >> (1 + ma_sl)) & 0x03;
- if (BX_DMA_THIS s[ma_sl].flip_flop==0) {
- BX_DMA_THIS s[ma_sl].flip_flop = !BX_DMA_THIS s[ma_sl].flip_flop;
- return(BX_DMA_THIS s[ma_sl].chan[channel].current_address & 0xff);
- }
- else {
- BX_DMA_THIS s[ma_sl].flip_flop = !BX_DMA_THIS s[ma_sl].flip_flop;
- return(BX_DMA_THIS s[ma_sl].chan[channel].current_address >> 8);
- }
-
- case 0x01: /* DMA-1 current count, channel 0 */
- case 0x03: /* DMA-1 current count, channel 1 */
- case 0x05: /* DMA-1 current count, channel 2 */
- case 0x07: /* DMA-1 current count, channel 3 */
- case 0xc2: /* DMA-2 current count, channel 0 */
- case 0xc6: /* DMA-2 current count, channel 1 */
- case 0xca: /* DMA-2 current count, channel 2 */
- case 0xce: /* DMA-2 current count, channel 3 */
- ma_sl = (address >= 0xc2);
- channel = (address >> (1 + ma_sl)) & 0x03;
- if (BX_DMA_THIS s[ma_sl].flip_flop==0) {
- BX_DMA_THIS s[ma_sl].flip_flop = !BX_DMA_THIS s[ma_sl].flip_flop;
- return(BX_DMA_THIS s[ma_sl].chan[channel].current_count & 0xff);
- }
- else {
- BX_DMA_THIS s[ma_sl].flip_flop = !BX_DMA_THIS s[ma_sl].flip_flop;
- return(BX_DMA_THIS s[ma_sl].chan[channel].current_count >> 8);
- }
-
- case 0x08: // DMA-1 Status Register
- case 0xd0: // DMA-2 Status Register
- // bit 7: 1 = channel 3 request
- // bit 6: 1 = channel 2 request
- // bit 5: 1 = channel 1 request
- // bit 4: 1 = channel 0 request
- // bit 3: 1 = channel 3 has reached terminal count
- // bit 2: 1 = channel 2 has reached terminal count
- // bit 1: 1 = channel 1 has reached terminal count
- // bit 0: 1 = channel 0 has reached terminal count
- // reading this register clears lower 4 bits (hold flags)
- ma_sl = (address == 0xd0);
- retval = BX_DMA_THIS s[ma_sl].status_reg;
- BX_DMA_THIS s[ma_sl].status_reg &= 0xf0;
- return(retval);
- break;
- case 0x0d: // DMA-1: temporary register
- case 0xda: // DMA-2: temporary register
- ma_sl = (address == 0xda);
- BX_ERROR(("DMA-%d: read of temporary register", ma_sl+1));
- // Note: write to 0x0D clears temporary register
- return(0);
- break;
-
- case 0x0081: // DMA-1 page register, channel 2
- case 0x0082: // DMA-1 page register, channel 3
- case 0x0083: // DMA-1 page register, channel 1
- case 0x0087: // DMA-1 page register, channel 0
- channel = channelindex[address - 0x81];
- return( BX_DMA_THIS s[0].chan[channel].page_reg );
-
- case 0x0089: // DMA-2 page register, channel 2
- case 0x008a: // DMA-2 page register, channel 3
- case 0x008b: // DMA-2 page register, channel 1
- case 0x008f: // DMA-2 page register, channel 0
- channel = channelindex[address - 0x89];
- return( BX_DMA_THIS s[1].chan[channel].page_reg );
-
- case 0x0084:
- case 0x0085:
- case 0x0086:
- case 0x0088:
- case 0x008c:
- case 0x008d:
- case 0x008e:
- BX_DEBUG(("read: extra page register 0x%04x unsupported", (unsigned) address));
- return(0);
-
- default:
- BX_ERROR(("read: unsupported address=%04x", (unsigned) address));
- return(0);
- }
-}
-
-
- // static IO port write callback handler
- // redirects to non-static class handler to avoid virtual functions
-
- void
-bx_dma_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len)
-{
-#if !BX_USE_DMA_SMF
- bx_dma_c *class_ptr = (bx_dma_c *) this_ptr;
-
- class_ptr->write(address, value, io_len);
-}
-
-
- /* 8237 DMA controller */
- void BX_CPP_AttrRegparmN(3)
-bx_dma_c::write(Bit32u address, Bit32u value, unsigned io_len)
-{
-#else
- UNUSED(this_ptr);
-#endif // !BX_USE_DMA_SMF
- Bit8u set_mask_bit;
- Bit8u channel;
- bx_bool ma_sl;
-
- if (io_len > 1) {
- if ( (io_len == 2) && (address == 0x0b) ) {
-#if BX_USE_DMA_SMF
- BX_DMA_THIS write_handler(NULL, address, value & 0xff, 1);
- BX_DMA_THIS write_handler(NULL, address+1, value >> 8, 1);
-#else
- BX_DMA_THIS write(address, value & 0xff, 1);
- BX_DMA_THIS write(address+1, value >> 8, 1);
-#endif
- return;
- }
-
- BX_ERROR(("io write to address %08x, len=%u",
- (unsigned) address, (unsigned) io_len));
- return;
- }
-
- BX_DEBUG(("write: address=%04x value=%02x",
- (unsigned) address, (unsigned) value));
-
-#if BX_DMA_FLOPPY_IO < 1
- /* if we're not supporting DMA/floppy IO just return */
- return;
-#endif
-
- switch (address) {
- case 0x00:
- case 0x02:
- case 0x04:
- case 0x06:
- case 0xc0:
- case 0xc4:
- case 0xc8:
- case 0xcc:
- ma_sl = (address >= 0xc0);
- channel = (address >> (1 + ma_sl)) & 0x03;
- BX_DEBUG((" DMA-%d base and current address, channel %d", ma_sl+1, channel));
- if (BX_DMA_THIS s[ma_sl].flip_flop==0) { /* 1st byte */
- BX_DMA_THIS s[ma_sl].chan[channel].base_address = value;
- BX_DMA_THIS s[ma_sl].chan[channel].current_address = value;
- }
- else { /* 2nd byte */
- BX_DMA_THIS s[ma_sl].chan[channel].base_address |= (value << 8);
- BX_DMA_THIS s[ma_sl].chan[channel].current_address |= (value << 8);
- BX_DEBUG((" base = %04x",
- (unsigned) BX_DMA_THIS s[ma_sl].chan[channel].base_address));
- BX_DEBUG((" curr = %04x",
- (unsigned) BX_DMA_THIS s[ma_sl].chan[channel].current_address));
- }
- BX_DMA_THIS s[ma_sl].flip_flop = !BX_DMA_THIS s[ma_sl].flip_flop;
- return;
- break;
-
- case 0x01:
- case 0x03:
- case 0x05:
- case 0x07:
- case 0xc2:
- case 0xc6:
- case 0xca:
- case 0xce:
- ma_sl = (address >= 0xc2);
- channel = (address >> (1 + ma_sl)) & 0x03;
- BX_DEBUG((" DMA-%d base and current count, channel %d", ma_sl+1, channel));
- if (BX_DMA_THIS s[ma_sl].flip_flop==0) { /* 1st byte */
- BX_DMA_THIS s[ma_sl].chan[channel].base_count = value;
- BX_DMA_THIS s[ma_sl].chan[channel].current_count = value;
- }
- else { /* 2nd byte */
- BX_DMA_THIS s[ma_sl].chan[channel].base_count |= (value << 8);
- BX_DMA_THIS s[ma_sl].chan[channel].current_count |= (value << 8);
- BX_DEBUG((" base = %04x",
- (unsigned) BX_DMA_THIS s[ma_sl].chan[channel].base_count));
- BX_DEBUG((" curr = %04x",
- (unsigned) BX_DMA_THIS s[ma_sl].chan[channel].current_count));
- }
- BX_DMA_THIS s[ma_sl].flip_flop = !BX_DMA_THIS s[ma_sl].flip_flop;
- return;
- break;
-
- case 0x08: /* DMA-1: command register */
- case 0xd0: /* DMA-2: command register */
- ma_sl = (address == 0xd0);
- if (value != 0x00)
- BX_ERROR(("write to command register: value(%02xh) not 0x00",
- (unsigned) value));
- BX_DMA_THIS s[ma_sl].command_reg = value;
- return;
- break;
-
- case 0x09: // DMA-1: request register
- case 0xd2: // DMA-2: request register
- ma_sl = (address == 0xd2);
- channel = value & 0x03;
- BX_ERROR(("DMA-%d: write to request register (%02x)", ma_sl+1, (unsigned) value));
- // note: write to 0x0d clears this register
- if (value & 0x04) {
- // set request bit
- BX_DMA_THIS s[ma_sl].status_reg |= (1 << (channel+4));
- BX_DEBUG(("DMA-%d: set request bit for channel %u", ma_sl+1, (unsigned) channel));
- }
- else {
- // clear request bit
- BX_DMA_THIS s[ma_sl].status_reg &= ~(1 << (channel+4));
- BX_DEBUG(("DMA-%d: cleared request bit for channel %u", ma_sl+1, (unsigned) channel));
- }
- control_HRQ(ma_sl);
- return;
- break;
-
- case 0x0a:
- case 0xd4:
- ma_sl = (address == 0xd4);
- set_mask_bit = value & 0x04;
- channel = value & 0x03;
- BX_DMA_THIS s[ma_sl].mask[channel] = (set_mask_bit > 0);
- BX_DEBUG(("DMA-%d: set_mask_bit=%u, channel=%u, mask now=%02xh", ma_sl+1,
- (unsigned) set_mask_bit, (unsigned) channel, (unsigned) BX_DMA_THIS s[ma_sl].mask[channel]));
- control_HRQ(ma_sl);
- return;
- break;
-
- case 0x0b: /* DMA-1 mode register */
- case 0xd6: /* DMA-2 mode register */
- ma_sl = (address == 0xd6);
- channel = value & 0x03;
- BX_DMA_THIS s[ma_sl].chan[channel].mode.mode_type = (value >> 6) & 0x03;
- BX_DMA_THIS s[ma_sl].chan[channel].mode.address_decrement = (value >> 5) & 0x01;
- BX_DMA_THIS s[ma_sl].chan[channel].mode.autoinit_enable = (value >> 4) & 0x01;
- BX_DMA_THIS s[ma_sl].chan[channel].mode.transfer_type = (value >> 2) & 0x03;
- BX_DEBUG(("DMA-%d: mode register[%u] = %02x", ma_sl+1,
- (unsigned) channel, (unsigned) value));
- return;
- break;
-
- case 0x0c: /* DMA-1 clear byte flip/flop */
- case 0xd8: /* DMA-2 clear byte flip/flop */
- ma_sl = (address == 0xd8);
- BX_DEBUG(("DMA-%d: clear flip/flop", ma_sl+1));
- BX_DMA_THIS s[ma_sl].flip_flop = 0;
- return;
- break;
-
- case 0x0d: // DMA-1: master clear
- case 0xda: // DMA-2: master clear
- ma_sl = (address == 0xda);
- BX_DEBUG(("DMA-%d: master clear", ma_sl+1));
- // writing any value to this port resets DMA controller 1 / 2
- // same action as a hardware reset
- // mask register is set (chan 0..3 disabled)
- // command, status, request, temporary, and byte flip-flop are all cleared
- reset_controller(ma_sl);
- return;
- break;
-
- case 0x0e: // DMA-1: clear mask register
- case 0xdc: // DMA-2: clear mask register
- ma_sl = (address == 0xdc);
- BX_DEBUG(("DMA-%d: clear mask register", ma_sl+1));
- BX_DMA_THIS s[ma_sl].mask[0] = 0;
- BX_DMA_THIS s[ma_sl].mask[1] = 0;
- BX_DMA_THIS s[ma_sl].mask[2] = 0;
- BX_DMA_THIS s[ma_sl].mask[3] = 0;
- control_HRQ(ma_sl);
- return;
- break;
-
- case 0x0f: // DMA-1: write all mask bits
- case 0xde: // DMA-2: write all mask bits
- ma_sl = (address == 0xde);
- BX_DEBUG(("DMA-%d: write all mask bits", ma_sl+1));
- BX_DMA_THIS s[ma_sl].mask[0] = value & 0x01; value >>= 1;
- BX_DMA_THIS s[ma_sl].mask[1] = value & 0x01; value >>= 1;
- BX_DMA_THIS s[ma_sl].mask[2] = value & 0x01; value >>= 1;
- BX_DMA_THIS s[ma_sl].mask[3] = value & 0x01;
- control_HRQ(ma_sl);
- return;
- break;
-
- case 0x81: /* DMA-1 page register, channel 2 */
- case 0x82: /* DMA-1 page register, channel 3 */
- case 0x83: /* DMA-1 page register, channel 1 */
- case 0x87: /* DMA-1 page register, channel 0 */
- /* address bits A16-A23 for DMA channel */
- channel = channelindex[address - 0x81];
- BX_DMA_THIS s[0].chan[channel].page_reg = value;
- BX_DEBUG(("DMA-1: page register %d = %02x", channel, (unsigned) value));
- return;
- break;
-
- case 0x89: /* DMA-2 page register, channel 2 */
- case 0x8a: /* DMA-2 page register, channel 3 */
- case 0x8b: /* DMA-2 page register, channel 1 */
- case 0x8f: /* DMA-2 page register, channel 0 */
- /* address bits A16-A23 for DMA channel */
- channel = channelindex[address - 0x89];
- BX_DMA_THIS s[1].chan[channel].page_reg = value;
- BX_DEBUG(("DMA-2: page register %d = %02x", channel + 4, (unsigned) value));
- return;
- break;
-
- case 0x0084:
- case 0x0085:
- case 0x0086:
- case 0x0088:
- case 0x008c:
- case 0x008d:
- case 0x008e:
- BX_DEBUG(("write: extra page register 0x%04x unsupported", (unsigned) address));
- return;
- break;
-
- default:
- BX_ERROR(("write ignored: %04xh = %02xh",
- (unsigned) address, (unsigned) value));
- }
-}
-
- void
-bx_dma_c::set_DRQ(unsigned channel, bx_bool val)
-{
- Bit32u dma_base, dma_roof;
- bx_bool ma_sl;
-
- if (channel > 7) {
- BX_PANIC(("set_DRQ() channel > 7"));
- return;
- }
- ma_sl = (channel > 3);
- BX_DMA_THIS s[ma_sl].DRQ[channel & 0x03] = val;
- if (!BX_DMA_THIS s[ma_sl].chan[channel & 0x03].used) {
- BX_PANIC(("set_DRQ(): channel %d not connected to device", channel));
- return;
- }
- channel &= 0x03;
- if (!val) {
- //BX_DEBUG(("bx_dma_c::DRQ(): val == 0"));
- // clear bit in status reg
- BX_DMA_THIS s[ma_sl].status_reg &= ~(1 << (channel+4));
-
- control_HRQ(ma_sl);
- return;
- }
-
-#if 0
- BX_INFO(("mask[%d]: %02x", channel, (unsigned) BX_DMA_THIS s[0].mask[channel]));
- BX_INFO(("flip_flop: %u", (unsigned) BX_DMA_THIS s[0].flip_flop));
- BX_INFO(("status_reg: %02x", (unsigned) BX_DMA_THIS s[0].status_reg));
- BX_INFO(("mode_type: %02x", (unsigned) BX_DMA_THIS s[0].chan[channel].mode.mode_type));
- BX_INFO(("address_decrement: %02x", (unsigned) BX_DMA_THIS s[0].chan[channel].mode.address_decrement));
- BX_INFO(("autoinit_enable: %02x", (unsigned) BX_DMA_THIS s[0].chan[channel].mode.autoinit_enable));
- BX_INFO(("transfer_type: %02x", (unsigned) BX_DMA_THIS s[0].chan[channel].mode.transfer_type));
- BX_INFO(("base_address: %04x", (unsigned) BX_DMA_THIS s[0].chan[channel].base_address));
- BX_INFO(("current_address: %04x", (unsigned) BX_DMA_THIS s[0].chan[channel].current_address));
- BX_INFO(("base_count: %04x", (unsigned) BX_DMA_THIS s[0].chan[channel].base_count));
- BX_INFO(("current_count: %04x", (unsigned) BX_DMA_THIS s[0].chan[channel].current_count));
- BX_INFO(("page_reg: %02x", (unsigned) BX_DMA_THIS s[0].chan[channel].page_reg));
-#endif
-
- BX_DMA_THIS s[ma_sl].status_reg |= (1 << (channel+4));
-
- if ( (BX_DMA_THIS s[ma_sl].chan[channel].mode.mode_type != DMA_MODE_SINGLE) &&
- (BX_DMA_THIS s[ma_sl].chan[channel].mode.mode_type != DMA_MODE_DEMAND) &&
- (BX_DMA_THIS s[ma_sl].chan[channel].mode.mode_type != DMA_MODE_CASCADE) )
- BX_PANIC(("set_DRQ: mode_type(%02x) not handled",
- (unsigned) BX_DMA_THIS s[ma_sl].chan[channel].mode.mode_type));
-
- dma_base = (BX_DMA_THIS s[ma_sl].chan[channel].page_reg << 16) |
- (BX_DMA_THIS s[ma_sl].chan[channel].base_address << ma_sl);
- if (BX_DMA_THIS s[ma_sl].chan[channel].mode.address_decrement==0) {
- dma_roof = dma_base + (BX_DMA_THIS s[ma_sl].chan[channel].base_count << ma_sl);
- } else {
- dma_roof = dma_base - (BX_DMA_THIS s[ma_sl].chan[channel].base_count << ma_sl);
- }
- if ( (dma_base & (0x7fff0000 << ma_sl)) != (dma_roof & (0x7fff0000 << ma_sl)) ) {
- BX_INFO(("dma_base = %08x", (unsigned) dma_base));
- BX_INFO(("dma_base_count = %08x", (unsigned) BX_DMA_THIS s[ma_sl].chan[channel].base_count));
- BX_INFO(("dma_roof = %08x", (unsigned) dma_roof));
- BX_PANIC(("request outside %dk boundary", 64 << ma_sl));
- }
-
- control_HRQ(ma_sl);
-}
-
- void
-bx_dma_c::control_HRQ(bx_bool ma_sl)
-{
- unsigned channel;
-
- // deassert HRQ if no DRQ is pending
- if ((BX_DMA_THIS s[ma_sl].status_reg & 0xf0) == 0) {
- if (ma_sl) {
- bx_pc_system.set_HRQ(0);
- } else {
- BX_DMA_THIS set_DRQ(4, 0);
- }
- return;
- }
- // find highest priority channel
- for (channel=0; channel<4; channel++) {
- if ( (BX_DMA_THIS s[ma_sl].status_reg & (1 << (channel+4))) &&
- (BX_DMA_THIS s[ma_sl].mask[channel]==0) ) {
- if (ma_sl) {
- // assert Hold ReQuest line to CPU
- bx_pc_system.set_HRQ(1);
- } else {
- // send DRQ to cascade channel of the master
- BX_DMA_THIS set_DRQ(4, 1);
- }
- break;
- }
- }
-}
-
- void
-bx_dma_c::raise_HLDA(void)
-{
- unsigned channel;
- Bit32u phy_addr;
- bx_bool count_expired = 0;
- bx_bool ma_sl = 0;
-
- BX_DMA_THIS HLDA = 1;
- // find highest priority channel
- for (channel=0; channel<4; channel++) {
- if ( (BX_DMA_THIS s[1].status_reg & (1 << (channel+4))) &&
- (BX_DMA_THIS s[1].mask[channel]==0) ) {
- ma_sl = 1;
- break;
- }
- }
- if (channel == 0) { // master cascade channel
- BX_DMA_THIS s[1].DACK[0] = 1;
- for (channel=0; channel<4; channel++) {
- if ( (BX_DMA_THIS s[0].status_reg & (1 << (channel+4))) &&
- (BX_DMA_THIS s[0].mask[channel]==0) ) {
- ma_sl = 0;
- break;
- }
- }
- }
- if (channel >= 4) {
- // wait till they're unmasked
- return;
- }
-
- //BX_DEBUG(("hlda: OK in response to DRQ(%u)", (unsigned) channel));
- phy_addr = (BX_DMA_THIS s[ma_sl].chan[channel].page_reg << 16) |
- (BX_DMA_THIS s[ma_sl].chan[channel].current_address << ma_sl);
-
- BX_DMA_THIS s[ma_sl].DACK[channel] = 1;
- // check for expiration of count, so we can signal TC and DACK(n)
- // at the same time.
- if (BX_DMA_THIS s[ma_sl].chan[channel].mode.address_decrement==0)
- BX_DMA_THIS s[ma_sl].chan[channel].current_address++;
- else
- BX_DMA_THIS s[ma_sl].chan[channel].current_address--;
- BX_DMA_THIS s[ma_sl].chan[channel].current_count--;
- if (BX_DMA_THIS s[ma_sl].chan[channel].current_count == 0xffff) {
- // count expired, done with transfer
- // assert TC, deassert HRQ & DACK(n) lines
- BX_DMA_THIS s[ma_sl].status_reg |= (1 << channel); // hold TC in status reg
- BX_DMA_THIS TC = 1;
- count_expired = 1;
- if (BX_DMA_THIS s[ma_sl].chan[channel].mode.autoinit_enable == 0) {
- // set mask bit if not in autoinit mode
- BX_DMA_THIS s[ma_sl].mask[channel] = 1;
- }
- else {
- // count expired, but in autoinit mode
- // reload count and base address
- BX_DMA_THIS s[ma_sl].chan[channel].current_address =
- BX_DMA_THIS s[ma_sl].chan[channel].base_address;
- BX_DMA_THIS s[ma_sl].chan[channel].current_count =
- BX_DMA_THIS s[ma_sl].chan[channel].base_count;
- }
- }
-
- Bit8u data_byte;
- Bit16u data_word;
-
- if (BX_DMA_THIS s[ma_sl].chan[channel].mode.transfer_type == 1) { // write
- // DMA controlled xfer of byte from I/O to Memory
-
- if (!ma_sl) {
- if (BX_DMA_THIS h[channel].dmaWrite8)
- BX_DMA_THIS h[channel].dmaWrite8(&data_byte);
- else
- BX_PANIC(("no dmaWrite handler for channel %u.", channel));
-
- BX_MEM_WRITE_PHYSICAL(phy_addr, 1, &data_byte);
-
- BX_DBG_DMA_REPORT(phy_addr, 1, BX_WRITE, data_byte);
- }
- else {
- if (BX_DMA_THIS h[channel].dmaWrite16)
- BX_DMA_THIS h[channel].dmaWrite16(&data_word);
- else
- BX_PANIC(("no dmaWrite handler for channel %u.", channel));
-
- BX_MEM_WRITE_PHYSICAL(phy_addr, 2, &data_word);
-
- BX_DBG_DMA_REPORT(phy_addr, 2, BX_WRITE, data_word);
- }
- }
- else if (BX_DMA_THIS s[ma_sl].chan[channel].mode.transfer_type == 2) { // read
- // DMA controlled xfer of byte from Memory to I/O
-
- if (!ma_sl) {
- BX_MEM_READ_PHYSICAL(phy_addr, 1, &data_byte);
-
- if (BX_DMA_THIS h[channel].dmaRead8)
- BX_DMA_THIS h[channel].dmaRead8(&data_byte);
-
- BX_DBG_DMA_REPORT(phy_addr, 1, BX_READ, data_byte);
- }
- else {
- BX_MEM_READ_PHYSICAL(phy_addr, 2, &data_word);
-
- if (BX_DMA_THIS h[channel].dmaRead16)
- BX_DMA_THIS h[channel].dmaRead16(&data_word);
-
- BX_DBG_DMA_REPORT(phy_addr, 2, BX_READ, data_word);
- }
- }
- else if (BX_DMA_THIS s[ma_sl].chan[channel].mode.transfer_type == 0) {
- // verify
-
- if (!ma_sl) {
- if (BX_DMA_THIS h[channel].dmaWrite8)
- BX_DMA_THIS h[channel].dmaWrite8(&data_byte);
- else
- BX_PANIC(("no dmaWrite handler for channel %u.", channel));
- }
- else {
- if (BX_DMA_THIS h[channel].dmaWrite16)
- BX_DMA_THIS h[channel].dmaWrite16(&data_word);
- else
- BX_PANIC(("no dmaWrite handler for channel %u.", channel));
- }
- }
- else {
- BX_PANIC(("hlda: transfer_type 3 is undefined"));
- }
-
- if (count_expired) {
- BX_DMA_THIS TC = 0; // clear TC, adapter card already notified
- BX_DMA_THIS HLDA = 0;
- bx_pc_system.set_HRQ(0); // clear HRQ to CPU
- BX_DMA_THIS s[ma_sl].DACK[channel] = 0; // clear DACK to adapter card
- if (!ma_sl) {
- BX_DMA_THIS set_DRQ(4, 0); // clear DRQ to cascade
- BX_DMA_THIS s[1].DACK[0] = 0; // clear DACK to cascade
- }
- }
-}
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: dma.h,v 1.15 2003/05/03 07:41:27 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-#ifndef _PCDMA_H
-#define _PCDMA_H
-
-
-#if BX_USE_DMA_SMF
-# define BX_DMA_SMF static
-# define BX_DMA_THIS theDmaDevice->
-#else
-# define BX_DMA_SMF
-# define BX_DMA_THIS this->
-#endif
-
-
-
-class bx_dma_c : public bx_dma_stub_c {
-public:
-
- bx_dma_c();
- ~bx_dma_c(void);
-
- virtual void init(void);
- virtual void bios_init(void);
- virtual void reset(unsigned type);
- virtual void raise_HLDA(void);
- virtual void set_DRQ(unsigned channel, bx_bool val);
- virtual unsigned get_TC(void);
-
- virtual unsigned registerDMA8Channel(unsigned channel,
- void (* dmaRead)(Bit8u *data_byte),
- void (* dmaWrite)(Bit8u *data_byte),
- const char *name);
- virtual unsigned registerDMA16Channel(unsigned channel,
- void (* dmaRead)(Bit16u *data_word),
- void (* dmaWrite)(Bit16u *data_word),
- const char *name);
- virtual unsigned unregisterDMAChannel(unsigned channel);
-
-private:
-
- static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len);
- static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len);
-#if !BX_USE_DMA_SMF
- Bit32u read( Bit32u address, unsigned io_len) BX_CPP_AttrRegparmN(2);
- void write(Bit32u address, Bit32u value, unsigned io_len) BX_CPP_AttrRegparmN(3);
-#endif
- BX_DMA_SMF void control_HRQ(bx_bool ma_sl);
- BX_DMA_SMF void reset_controller(unsigned num);
-
- struct {
- bx_bool DRQ[4]; // DMA Request
- bx_bool DACK[4]; // DMA Acknowlege
-
- bx_bool mask[4];
- bx_bool flip_flop;
- Bit8u status_reg;
- Bit8u command_reg;
- Bit8u request_reg;
- Bit8u temporary_reg;
- struct {
- struct {
- Bit8u mode_type;
- Bit8u address_decrement;
- Bit8u autoinit_enable;
- Bit8u transfer_type;
- } mode;
- Bit16u base_address;
- Bit16u current_address;
- Bit16u base_count;
- Bit16u current_count;
- Bit8u page_reg;
- bx_bool used;
- } chan[4]; /* DMA channels 0..3 */
- } s[2]; // state information DMA-1 / DMA-2
-
- bx_bool HLDA; // Hold Acknowlege
- bx_bool TC; // Terminal Count
-
- struct {
- void (* dmaRead8)(Bit8u *data_byte);
- void (* dmaWrite8)(Bit8u *data_byte);
- void (* dmaRead16)(Bit16u *data_word);
- void (* dmaWrite16)(Bit16u *data_word);
- } h[4]; // DMA read and write handlers
-
- };
-
-#endif // #ifndef _PCDMA_H
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: eth.cc,v 1.16 2003/04/28 13:01:09 cbothamy Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2001 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-// eth.cc - helper code to find and create pktmover classes
-
-// Peter Grehan (grehan@iprg.nokia.com) coded all of this
-// NE2000/ether stuff.
-
-// Define BX_PLUGGABLE in files that can be compiled into plugins. For
-// platforms that require a special tag on exported symbols, BX_PLUGGABLE
-// is used to know when we are exporting symbols and when we are importing.
-#define BX_PLUGGABLE
-
-#include "bochs.h"
-#if BX_NE2K_SUPPORT
-
-#define LOG_THIS /* not needed */
-
-eth_locator_c *eth_locator_c::all;
-
-//
-// Each pktmover module has a static locator class that registers
-// here
-//
-eth_locator_c::eth_locator_c(const char *type)
-{
- next = all;
- all = this;
- this->type = type;
-}
-
-#ifdef ETH_NULL
-extern class bx_null_locator_c bx_null_match;
-#endif
-#ifdef ETH_FBSD
-extern class bx_fbsd_locator_c bx_fbsd_match;
-#endif
-#ifdef ETH_LINUX
-extern class bx_linux_locator_c bx_linux_match;
-#endif
-#ifdef ETH_WIN32
-extern class bx_win32_locator_c bx_win32_match;
-#endif
-#if HAVE_ETHERTAP
-extern class bx_tap_locator_c bx_tap_match;
-#endif
-#if HAVE_TUNTAP
-extern class bx_tuntap_locator_c bx_tuntap_match;
-#endif
-#ifdef ETH_TEST
-extern bx_test_match;
-#endif
-#ifdef ETH_ARPBACK
-extern class bx_arpback_locator_c bx_arpback_match;
-#endif
-
-//
-// Called by ethernet chip emulations to locate and create a pktmover
-// object
-//
-eth_pktmover_c *
-eth_locator_c::create(const char *type, const char *netif,
- const char *macaddr,
- eth_rx_handler_t rxh, void *rxarg)
-{
-#ifdef eth_static_constructors
- for (eth_locator_c *p = all; p != NULL; p = p->next) {
- if (strcmp(type, p->type) == 0)
- return (p->allocate(netif, macaddr, rxh, rxarg));
- }
-#else
- eth_locator_c *ptr = 0;
-
-#ifdef ETH_ARPBACK
- {
- if (!strcmp(type, "arpback"))
- ptr = (eth_locator_c *) &bx_arpback_match;
- }
-#endif
-#ifdef ETH_NULL
- {
- if (!strcmp(type, "null"))
- ptr = (eth_locator_c *) &bx_null_match;
- }
-#endif
-#ifdef ETH_FBSD
- {
- if (!strcmp(type, "fbsd"))
- ptr = (eth_locator_c *) &bx_fbsd_match;
- }
-#endif
-#ifdef ETH_LINUX
- {
- if (!strcmp(type, "linux"))
- ptr = (eth_locator_c *) &bx_linux_match;
- }
-#endif
-#if HAVE_TUNTAP
- {
- if (!strcmp(type, "tuntap"))
- ptr = (eth_locator_c *) &bx_tuntap_match;
- }
-#endif
-#if HAVE_ETHERTAP
- {
- if (!strcmp(type, "tap"))
- ptr = (eth_locator_c *) &bx_tap_match;
- }
-#endif
-#ifdef ETH_WIN32
- {
- if(!strcmp(type, "win32"))
- ptr = (eth_locator_c *) &bx_win32_match;
- }
-#endif
-#ifdef ETH_TEST
- {
- if (!strcmp(type, "test"))
- ptr = (eth_locator_c *) &bx_test_match;
- }
-#endif
- if (ptr)
- return (ptr->allocate(netif, macaddr, rxh, rxarg));
-#endif
-
- return (NULL);
-}
-
-#if (HAVE_ETHERTAP==1) || (HAVE_TUNTAP==1)
-
-extern "C" {
-#include <sys/wait.h>
-};
-
-#undef LOG_THIS
-#define LOG_THIS bx_devices.pluginNE2kDevice->
-
-// This is a utility script used for tuntap or ethertap
-int execute_script( char* scriptname, char* arg1 )
-{
- int pid,status;
-
- if (!(pid=fork())) {
- char filename[BX_PATHNAME_LEN];
- if ( scriptname[0]=='/' ) {
- strcpy (filename, scriptname);
- }
- else {
- getcwd (filename, BX_PATHNAME_LEN);
- strcat (filename, "/");
- strcat (filename, scriptname);
- }
-
- // execute the script
- BX_INFO(("Executing script '%s %s'",filename,arg1));
- execle(filename, scriptname, arg1, NULL, NULL);
-
- // if we get here there has been a problem
- exit(-1);
- }
-
- wait (&status);
- if (!WIFEXITED(status)) {
- return -1;
- }
- return WEXITSTATUS(status);
-}
-
-#endif // (HAVE_ETHERTAP==1) || (HAVE_TUNTAP==1)
-
-#endif /* if BX_NE2K_SUPPORT */
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: eth.h,v 1.12 2003/04/26 14:48:45 cbothamy Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2001 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-// Peter Grehan (grehan@iprg.nokia.com) coded all of this
-// NE2000/ether stuff.
-
-// eth.h - see eth_null.cc for implementation details
-
-typedef void (*eth_rx_handler_t)(void *arg, const void *buf, unsigned len);
-
-int execute_script(char *name, char* arg1);
-
-//
-// The eth_pktmover class is used by ethernet chip emulations
-// to interface to the outside world. An instance of this
-// would allow frames to be sent to and received from some
-// entity. An example would be the packet filter on a Unix
-// system, an NDIS driver in promisc mode on WinNT, or maybe
-// a simulated network that talks to another process.
-//
-class eth_pktmover_c {
-public:
- virtual void sendpkt(void *buf, unsigned io_len) = 0;
- virtual ~eth_pktmover_c (void) {}
-protected:
- eth_rx_handler_t rxh; // receive callback
- void *rxarg;
-};
-
-
-//
-// The eth_locator class is used by pktmover classes to register
-// their name. Chip emulations use the static 'create' method
-// to locate and instantiate a pktmover class.
-//
-class eth_locator_c {
-public:
- static eth_pktmover_c *create(const char *type, const char *netif,
- const char *macaddr,
- eth_rx_handler_t rxh,
- void *rxarg);
-protected:
- eth_locator_c(const char *type);
- virtual eth_pktmover_c *allocate(const char *netif,
- const char *macaddr,
- eth_rx_handler_t rxh,
- void *rxarg) = 0;
-private:
- static eth_locator_c *all;
- eth_locator_c *next;
- const char *type;
-};
-
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: eth_arpback.cc,v 1.11 2002/11/20 19:06:22 bdenney Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2001 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-// eth_arpback.cc - basic ethernet packetmover, only responds to ARP
-
-// Various networking docs:
-// http://www.graphcomp.com/info/rfc/
-// rfc0826: arp
-// rfc0903: rarp
-
-// Define BX_PLUGGABLE in files that can be compiled into plugins. For
-// platforms that require a special tag on exported symbols, BX_PLUGGABLE
-// is used to know when we are exporting symbols and when we are importing.
-#define BX_PLUGGABLE
-
-#include "bochs.h"
-
-#if BX_NE2K_SUPPORT && defined(ETH_ARPBACK)
-
-#include "crc32.h"
-#include "eth_packetmaker.h"
-#define LOG_THIS bx_devices.pluginNE2kDevice->
-
-
-//static const Bit8u external_mac[]={0xB0, 0xC4, 0x20, 0x20, 0x00, 0x00, 0x00};
-//static const Bit8u internal_mac[]={0xB0, 0xC4, 0x20, 0x00, 0x00, 0x00, 0x00};
-//static const Bit8u external_ip[]={ 192, 168, 0, 2, 0x00 };
-//static const Bit8u broadcast_mac[]={0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00};
-//static const Bit8u ethtype_arp[]={0x08, 0x06, 0x00};
-
-#define MAX_FRAME_SIZE 2048
-
-//
-// Define the class. This is private to this module
-//
-class bx_arpback_pktmover_c : public eth_pktmover_c {
-public:
- bx_arpback_pktmover_c(const char *netif, const char *macaddr,
- eth_rx_handler_t rxh,
- void *rxarg);
- void sendpkt(void *buf, unsigned io_len);
-private:
- int rx_timer_index;
- static void rx_timer_handler(void *);
- void rx_timer(void);
- FILE *txlog, *txlog_txt;
- //Bit8u arpbuf[MAX_FRAME_SIZE];
- //Bit32u buflen;
- //bx_bool bufvalid;
- //CRC_Generator mycrc;
- eth_ETHmaker packetmaker;
-};
-
-
-//
-// Define the static class that registers the derived pktmover class,
-// and allocates one on request.
-//
-class bx_arpback_locator_c : public eth_locator_c {
-public:
- bx_arpback_locator_c(void) : eth_locator_c("arpback") {}
-protected:
- eth_pktmover_c *allocate(const char *netif, const char *macaddr,
- eth_rx_handler_t rxh,
- void *rxarg) {
- return (new bx_arpback_pktmover_c(netif, macaddr, rxh, rxarg));
- }
-} bx_arpback_match;
-
-
-//
-// Define the methods for the bx_arpback_pktmover derived class
-//
-
-// the constructor
-bx_arpback_pktmover_c::bx_arpback_pktmover_c(const char *netif,
- const char *macaddr,
- eth_rx_handler_t rxh,
- void *rxarg)
-{
- this->rx_timer_index =
- bx_pc_system.register_timer(this, this->rx_timer_handler, 1000,
- 1, 1, "eth_arpback"); // continuous, active
- this->rxh = rxh;
- this->rxarg = rxarg;
- //bufvalid=0;
- packetmaker.init();
-#if BX_ETH_NULL_LOGGING
- // Start the rx poll
- // eventually Bryce wants txlog to dump in pcap format so that
- // tcpdump -r FILE can read it and interpret packets.
- txlog = fopen ("ne2k-tx.log", "wb");
- if (!txlog) BX_PANIC (("open ne2k-tx.log failed"));
- txlog_txt = fopen ("ne2k-txdump.txt", "wb");
- if (!txlog_txt) BX_PANIC (("open ne2k-txdump.txt failed"));
- fprintf (txlog_txt, "arpback packetmover readable log file\n");
- fprintf (txlog_txt, "net IF = %s\n", netif);
- fprintf (txlog_txt, "MAC address = ");
- for (int i=0; i<6; i++)
- fprintf (txlog_txt, "%02x%s", 0xff & macaddr[i], i<5?":" : "");
- fprintf (txlog_txt, "\n--\n");
- fflush (txlog_txt);
-#endif
-}
-
-void
-bx_arpback_pktmover_c::sendpkt(void *buf, unsigned io_len)
-{
- if(io_len<MAX_FRAME_SIZE) {
- eth_packet barney;
- memcpy(barney.buf,buf,io_len);
- barney.len=io_len;
- if(packetmaker.ishandler(barney)) {
- packetmaker.sendpacket(barney);
- }
- /*
- if(( (!memcmp(buf, external_mac, 6)) || (!memcmp(buf, broadcast_mac, 6)) )
- && (!memcmp(((Bit8u *)buf)+12, ethtype_arp, 2)) ) {
- Bit32u tempcrc;
- memcpy(arpbuf,buf,io_len); //move to temporary buffer
- memcpy(arpbuf, arpbuf+6, 6); //set destination to sender
- memcpy(arpbuf+6, external_mac, 6); //set sender to us
- memcpy(arpbuf+32, arpbuf+22, 10); //move destination to sender
- memcpy(arpbuf+22, external_mac, 6); //set sender to us
- memcpy(arpbuf+28, external_ip, 4); //set sender to us
- arpbuf[21]=2; //make this a reply and not a request
- tempcrc=mycrc.get_CRC(arpbuf,io_len);
- memcpy(arpbuf+io_len, &tempcrc, 4);
- buflen=io_len;//+4
- bufvalid=1;
- }
- */
- }
-#if BX_ETH_NULL_LOGGING
- BX_DEBUG (("sendpkt length %u", io_len));
- // dump raw bytes to a file, eventually dump in pcap format so that
- // tcpdump -r FILE can interpret them for us.
- int n = fwrite (buf, io_len, 1, txlog);
- if (n != 1) BX_ERROR (("fwrite to txlog failed", io_len));
- // dump packet in hex into an ascii log file
- fprintf (txlog_txt, "NE2K transmitting a packet, length %u\n", io_len);
- Bit8u *charbuf = (Bit8u *)buf;
- for (n=0; n<io_len; n++) {
- if (((n % 16) == 0) && n>0)
- fprintf (txlog_txt, "\n");
- fprintf (txlog_txt, "%02x ", charbuf[n]);
- }
- fprintf (txlog_txt, "\n--\n");
- // flush log so that we see the packets as they arrive w/o buffering
- fflush (txlog);
- fflush (txlog_txt);
-#endif
-}
-
-void bx_arpback_pktmover_c::rx_timer_handler (void * this_ptr)
-{
-#if BX_ETH_NULL_LOGGING
- BX_DEBUG (("rx_timer_handler"));
-#endif
- bx_arpback_pktmover_c *class_ptr = ((bx_arpback_pktmover_c *)this_ptr);
-
- class_ptr->rx_timer();
-}
-
-void bx_arpback_pktmover_c::rx_timer (void)
-{
- int nbytes = 0;
- struct bpf_hdr *bhdr;
- eth_packet rubble;
-
- if(packetmaker.getpacket(rubble)) {
- //bufvalid=0;
- void * buf=rubble.buf;
- unsigned io_len=rubble.len;
- Bit32u n;
- fprintf (txlog_txt, "NE2K receiving a packet, length %u\n", io_len);
- Bit8u *charbuf = (Bit8u *)buf;
- for (n=0; n<io_len; n++) {
- if (((n % 16) == 0) && n>0)
- fprintf (txlog_txt, "\n");
- fprintf (txlog_txt, "%02x ", charbuf[n]);
- }
- fprintf (txlog_txt, "\n--\n");
- fflush (txlog_txt);
-
- (*rxh)(rxarg, buf, io_len);
- }
-}
-
-#endif /* if BX_NE2K_SUPPORT && defined(ETH_ARPBACK) */
-
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: eth_fbsd.cc,v 1.26 2002/11/20 19:06:22 bdenney Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2001 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-// Peter Grehan (grehan@iprg.nokia.com) coded all of this
-// NE2000/ether stuff.
-
-// eth_fbsd.cc - A FreeBSD packet filter implementation of
-// an ethernet pktmover. There are some problems and limitations
-// with FreeBSD:
-// - the source address of the frame is overwritten by
-// the hosts's source address. This causes problems with
-// learning bridges - since they cannot determine where
-// BOCHS 'is', they broadcast the frame to all ports.
-// - packets cannot be sent from BOCHS to the host
-// - TCP performance seems to be abysmal; I think this is
-// a timing problem somewhere.
-// - I haven't handled the case where multiple frames arrive
-// in a single BPF read.
-//
-// The /dev/bpf* devices need to be set up with the appropriate
-// permissions for this to work.
-//
-// The config line in .bochsrc should look something like:
-//
-// ne2k: ioaddr=0x280, irq=9, mac=00:a:b:c:1:2, ethmod=fbsd, ethdev=fxp0
-//
-
-// Define BX_PLUGGABLE in files that can be compiled into plugins. For
-// platforms that require a special tag on exported symbols, BX_PLUGGABLE
-// is used to know when we are exporting symbols and when we are importing.
-#define BX_PLUGGABLE
-
-#include "bochs.h"
-#if BX_NE2K_SUPPORT && defined(ETH_FBSD)
-
-#define LOG_THIS bx_devices.pluginNE2kDevice->
-
-extern "C" {
-#include <fcntl.h>
-#include <sys/ioctl.h>
-#include <sys/socket.h>
-#include <net/if.h>
-#include <net/bpf.h>
-#include <errno.h>
-};
-
-#define BX_BPF_POLL 1000 // Poll for a frame every 250 usecs
-
-#define BX_BPF_BUFSIZ 2048 // enough for an ether frame + bpf hdr
-
-#define BX_BPF_INSNSIZ 8 // number of bpf insns
-
-// template filter for a unicast mac address and all
-// multicast/broadcast frames
-static const struct bpf_insn macfilter[] = {
- BPF_STMT(BPF_LD|BPF_W|BPF_ABS, 2), // A <- P[2:4]
- BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 0xaaaaaaaa, 0, 2), // if A != 0xaaaaaaa GOTO LABEL-1
- BPF_STMT(BPF_LD|BPF_H|BPF_ABS, 0), // A <- P[0:2]
- BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 0x0000aaaa, 2, 0), // if A == 0xaaaa GOTO ACCEPT
- // LABEL-1
- BPF_STMT(BPF_LD|BPF_B|BPF_ABS, 0), // A <- P[0:1]
- BPF_JUMP(BPF_JMP|BPF_JSET|BPF_K, 0x01, 0, 1), // if !(A & 1) GOTO LABEL-REJECT
- // LABEL-ACCEPT
- BPF_STMT(BPF_RET, 1514), // Accept packet
- // LABEL-REJECT
- BPF_STMT(BPF_RET, 0), // Reject packet
-};
-
-// template filter for all frames
-static const struct bpf_insn promiscfilter[] = {
- BPF_STMT(BPF_RET, 1514)
-};
-
-//
-// Define the class. This is private to this module
-//
-class bx_fbsd_pktmover_c : public eth_pktmover_c {
-public:
- bx_fbsd_pktmover_c(const char *netif,
- const char *macaddr,
- eth_rx_handler_t rxh,
- void *rxarg);
- void sendpkt(void *buf, unsigned io_len);
-
-private:
- char *fbsd_macaddr[6];
- int bpf_fd;
- static void rx_timer_handler(void *);
- void rx_timer(void);
- int rx_timer_index;
- struct bpf_insn filter[BX_BPF_INSNSIZ];
- FILE *ne2klog, *ne2klog_txt;
-};
-
-
-//
-// Define the static class that registers the derived pktmover class,
-// and allocates one on request.
-//
-class bx_fbsd_locator_c : public eth_locator_c {
-public:
- bx_fbsd_locator_c(void) : eth_locator_c("fbsd") {}
-protected:
- eth_pktmover_c *allocate(const char *netif,
- const char *macaddr,
- eth_rx_handler_t rxh,
- void *rxarg) {
- return (new bx_fbsd_pktmover_c(netif, macaddr, rxh, rxarg));
- }
-} bx_fbsd_match;
-
-
-//
-// Define the methods for the bx_fbsd_pktmover derived class
-//
-
-// the constructor
-//
-// Open a bpf file descriptor, and attempt to bind to
-// the specified netif (Replicates libpcap open code)
-//
-bx_fbsd_pktmover_c::bx_fbsd_pktmover_c(const char *netif,
- const char *macaddr,
- eth_rx_handler_t rxh,
- void *rxarg)
-{
- char device[sizeof "/dev/bpf000"];
- int tmpfd;
- int n = 0;
- struct ifreq ifr;
- struct bpf_version bv;
- struct bpf_program bp;
- u_int v;
-
- memcpy(fbsd_macaddr, macaddr, 6);
-
- do {
- (void)sprintf(device, "/dev/bpf%d", n++);
- this->bpf_fd = open(device, O_RDWR);
- BX_DEBUG(("tried %s, returned %d (%s)",device,this->bpf_fd,strerror(errno)));
- if(errno == EACCES)
- break;
- } while (this->bpf_fd == -1);
-
- if (this->bpf_fd == -1) {
- BX_PANIC(("eth_freebsd: could not open packet filter: %s", strerror(errno)));
- return;
- }
-
- if (ioctl(this->bpf_fd, BIOCVERSION, (caddr_t)&bv) < 0) {
- BX_PANIC(("eth_freebsd: could not retrieve bpf version"));
- close(this->bpf_fd);
- this->bpf_fd = -1;
- return;
- }
- if (bv.bv_major != BPF_MAJOR_VERSION || bv.bv_minor < BPF_MINOR_VERSION) {
- BX_PANIC(("eth_freebsd: bpf version mismatch between compilation and runtime"));
- close(this->bpf_fd);
- this->bpf_fd = -1;
- return;
- }
-
- // Set buffer size
- v = BX_BPF_BUFSIZ;
- if (ioctl(this->bpf_fd, BIOCSBLEN, (caddr_t)&v) < 0) {
- BX_PANIC(("eth_freebsd: could not set buffer size: %s", strerror(errno)));
- close(this->bpf_fd);
- this->bpf_fd = -1;
- return;
- }
-
- (void)strncpy(ifr.ifr_name, netif, sizeof(ifr.ifr_name));
- if (ioctl(this->bpf_fd, BIOCSETIF, (caddr_t)&ifr) < 0) {
- BX_PANIC(("eth_freebsd: could not enable interface '%s': %s", netif, strerror(errno)));
- close(this->bpf_fd);
- this->bpf_fd == -1;
- }
-
- // Verify that the device is an ethernet.
- if (ioctl(this->bpf_fd, BIOCGDLT, (caddr_t)&v) < 0) {
- BX_PANIC(("eth_freebsd: could not retrieve datalink type: %s", strerror(errno)));
- close(this->bpf_fd);
- this->bpf_fd = -1;
- return;
- }
- if (v != DLT_EN10MB) {
- BX_PANIC(("eth_freebsd: incorrect datalink type %d, expected 10mb ethernet", v));
- close(this->bpf_fd);
- this->bpf_fd = -1;
- return;
- }
-
- // Put the device into promisc mode. This could be optimised
- // to filter on a MAC address, broadcast, and all-multi,
- // but this will do for now.
- //
- if (ioctl(this->bpf_fd, BIOCPROMISC, NULL) < 0) {
- BX_PANIC(("eth_freebsd: could not enable promisc mode: %s", strerror(errno)));
- close(this->bpf_fd);
- this->bpf_fd = -1;
- return;
- }
-
- // Set up non-blocking i/o
- v = 1;
- if (ioctl(this->bpf_fd, FIONBIO, &v) < 0) {
- BX_PANIC(("eth_freebsd: could not enable non-blocking i/o: %s", strerror(errno)));
- close(this->bpf_fd);
- this->bpf_fd = -1;
- return;
- }
-
- // Install a filter
-#ifdef notdef
- memcpy(&this->filter, promiscfilter, sizeof(promiscfilter));
- bp.bf_len = 1;
-#else
- memcpy(&this->filter, macfilter, sizeof(macfilter));
- this->filter[1].k =
- (macaddr[2] & 0xff) << 24 |
- (macaddr[3] & 0xff) << 16 |
- (macaddr[4] & 0xff) << 8 |
- (macaddr[5] & 0xff);
- this->filter[3].k =
- (macaddr[0] & 0xff) << 8 |
- (macaddr[1] & 0xff);
- bp.bf_len = 8;
-#endif
- bp.bf_insns = &this->filter[0];
- if (ioctl(this->bpf_fd, BIOCSETF, &bp) < 0) {
- BX_PANIC(("eth_freebsd: could not set filter: %s", strerror(errno)));
- close(this->bpf_fd);
- this->bpf_fd = -1;
- return;
- }
-
- // Start the rx poll
- this->rx_timer_index =
- bx_pc_system.register_timer(this, this->rx_timer_handler, BX_BPF_POLL,
- 1, 1, "eth_fbsd"); // continuous, active
-
- this->rxh = rxh;
- this->rxarg = rxarg;
-
-#if BX_ETH_FBSD_LOGGING
- // eventually Bryce wants ne2klog to dump in pcap format so that
- // tcpdump -r FILE can read it and interpret packets.
- ne2klog = fopen ("ne2k.raw", "wb");
- if (!ne2klog) BX_PANIC (("open ne2k-tx.log failed"));
- ne2klog_txt = fopen ("ne2k.txt", "wb");
- if (!ne2klog_txt) BX_PANIC (("open ne2k-txdump.txt failed"));
- fprintf (ne2klog_txt, "null packetmover readable log file\n");
- fprintf (ne2klog_txt, "net IF = %s\n", netif);
- fprintf (ne2klog_txt, "MAC address = ");
- for (int i=0; i<6; i++)
- fprintf (ne2klog_txt, "%02x%s", 0xff & macaddr[i], i<5?":" : "");
- fprintf (ne2klog_txt, "\n--\n");
- fflush (ne2klog_txt);
-#endif
-}
-
-// the output routine - called with pre-formatted ethernet frame.
-void
-bx_fbsd_pktmover_c::sendpkt(void *buf, unsigned io_len)
-{
-#if BX_ETH_FBSD_LOGGING
- BX_DEBUG (("sendpkt length %u", io_len));
- // dump raw bytes to a file, eventually dump in pcap format so that
- // tcpdump -r FILE can interpret them for us.
- int n = fwrite (buf, io_len, 1, ne2klog);
- if (n != 1) BX_ERROR (("fwrite to ne2klog failed", io_len));
- // dump packet in hex into an ascii log file
- fprintf (ne2klog_txt, "NE2K TX packet, length %u\n", io_len);
- Bit8u *charbuf = (Bit8u *)buf;
- for (n=0; n<io_len; n++) {
- if (((n % 16) == 0) && n>0)
- fprintf (ne2klog_txt, "\n");
- fprintf (ne2klog_txt, "%02x ", charbuf[n]);
- }
- fprintf (ne2klog_txt, "\n--\n");
- // flush log so that we see the packets as they arrive w/o buffering
- fflush (ne2klog);
- fflush (ne2klog_txt);
-#endif
- int status;
-
- if (this->bpf_fd != -1)
- status = write(this->bpf_fd, buf, io_len);
-}
-
-// The receive poll process
-void
-bx_fbsd_pktmover_c::rx_timer_handler(void *this_ptr)
-{
- bx_fbsd_pktmover_c *class_ptr = (bx_fbsd_pktmover_c *) this_ptr;
-
- class_ptr->rx_timer();
-}
-
-
-void
-bx_fbsd_pktmover_c::rx_timer(void)
-{
- int nbytes = 0;
- unsigned char rxbuf[BX_BPF_BUFSIZ];
- struct bpf_hdr *bhdr;
- struct bpf_stat bstat;
- static struct bpf_stat previous_bstat;
- int counter = 10;
-#define phdr ((unsigned char*)bhdr)
-
- bhdr = (struct bpf_hdr *) rxbuf;
- nbytes = read(this->bpf_fd, rxbuf, sizeof(rxbuf));
-
- while (phdr < (rxbuf + nbytes)) {
- if (ioctl(this->bpf_fd, BIOCGSTATS, &bstat) < 0) {
- BX_PANIC(("eth_freebsd: could not stat filter: %s", strerror(errno)));
- }
- if (bstat.bs_drop > previous_bstat.bs_drop) {
- BX_INFO (("eth_freebsd: %d packets dropped by the kernel.",
- bstat.bs_drop - previous_bstat.bs_drop));
- }
- previous_bstat = bstat;
- if (bhdr->bh_caplen < 20 || bhdr->bh_caplen > 1514) {
- BX_ERROR(("eth_freebsd: received too weird packet length: %d", bhdr->bh_caplen));
- }
-
- // filter out packets sourced from this node
- if (memcmp(bhdr + bhdr->bh_hdrlen + 6, this->fbsd_macaddr, 6)) {
- (*rxh)(rxarg, phdr + bhdr->bh_hdrlen, bhdr->bh_caplen);
- }
-
-#if BX_ETH_FBSD_LOGGING
- /// hey wait there is no receive data with a NULL ethernet, is there....
- BX_DEBUG (("receive packet length %u", nbytes));
- // dump raw bytes to a file, eventually dump in pcap format so that
- // tcpdump -r FILE can interpret them for us.
- if (1 != fwrite (bhdr, bhdr->bh_caplen, 1, ne2klog)) {
- BX_PANIC (("fwrite to ne2klog failed: %s", strerror(errno)));
- }
- // dump packet in hex into an ascii log file
- fprintf (this->ne2klog_txt, "NE2K RX packet, length %u\n", bhdr->bh_caplen);
- Bit8u *charrxbuf = (Bit8u *)rxbuf;
- int n;
- for (n=0; n<bhdr->bh_caplen; n++) {
- if (((n % 16) == 0) && n>0)
- fprintf (this->ne2klog_txt, "\n");
- fprintf (this->ne2klog_txt, "%02x ", phdr[n]);
- }
- fprintf (this->ne2klog_txt, "\n--\n");
- // flush log so that we see the packets as they arrive w/o buffering
- fflush (this->ne2klog);
- fflush (this->ne2klog_txt);
-#endif
-
- // Advance bhdr and phdr pointers to next packet
- bhdr = (struct bpf_hdr*) ((char*) bhdr + BPF_WORDALIGN(bhdr->bh_hdrlen + bhdr->bh_caplen));
- }
-}
-
-#endif /* if BX_NE2K_SUPPORT && defined(ETH_FBSD) */
-
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: eth_linux.cc,v 1.14 2003/02/16 19:35:57 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2001 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-// Peter Grehan (grehan@iprg.nokia.com) coded all of this
-// NE2000/ether stuff.
-
-// eth_linux.cc - A Linux socket filter adaptation of the FreeBSD BPF driver
-// <splite@purdue.edu> 21 June 2001
-//
-// Problems and limitations:
-// - packets cannot be sent from BOCHS to the host
-// - Linux kernel sometimes gets network watchdog timeouts under emulation
-// - author doesn't know C++
-//
-// The config line in .bochsrc should look something like:
-//
-// ne2k: ioaddr=0x280, irq=10, mac=00:a:b:c:1:2, ethmod=linux, ethdev=eth0
-//
-
-// Define BX_PLUGGABLE in files that can be compiled into plugins. For
-// platforms that require a special tag on exported symbols, BX_PLUGGABLE
-// is used to know when we are exporting symbols and when we are importing.
-#define BX_PLUGGABLE
-
-#include "bochs.h"
-#if BX_NE2K_SUPPORT && defined (ETH_LINUX)
-#define LOG_THIS bx_devices.pluginNE2kDevice->
-
-extern "C" {
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <netpacket/packet.h>
-#include <netinet/in.h>
-#include <net/ethernet.h>
-#include <net/if.h>
-#include <linux/types.h>
-#include <linux/filter.h>
-};
-
-#define BX_PACKET_POLL 1000 // Poll for a frame every 1000 usecs
-
-#define BX_PACKET_BUFSIZ 2048 // Enough for an ether frame
-
-// template filter for a unicast mac address and all
-// multicast/broadcast frames
-static const struct sock_filter macfilter[] = {
- BPF_STMT(BPF_LD|BPF_W|BPF_ABS, 2),
- BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 0xaaaaaaaa, 0, 2),
- BPF_STMT(BPF_LD|BPF_H|BPF_ABS, 0),
- BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, 0x0000aaaa, 2, 0),
- BPF_STMT(BPF_LD|BPF_B|BPF_ABS, 0),
- BPF_JUMP(BPF_JMP|BPF_JSET|BPF_K, 0x01, 0, 1),
- BPF_STMT(BPF_RET, 1514),
- BPF_STMT(BPF_RET, 0),
-};
-#define BX_LSF_ICNT 8 // number of lsf instructions in macfilter
-
-#if 0
-// template filter for all frames
-static const struct sock_filter promiscfilter[] = {
- BPF_STMT(BPF_RET, 1514)
-};
-#endif
-
-//
-// Define the class. This is private to this module
-//
-class bx_linux_pktmover_c : public eth_pktmover_c {
-public:
- bx_linux_pktmover_c(const char *netif,
- const char *macaddr,
- eth_rx_handler_t rxh,
- void *rxarg);
- void sendpkt(void *buf, unsigned io_len);
-
-private:
- unsigned char *linux_macaddr[6];
- int fd;
- int ifindex;
- static void rx_timer_handler(void *);
- void rx_timer(void);
- int rx_timer_index;
- struct sock_filter filter[BX_LSF_ICNT];
-};
-
-
-//
-// Define the static class that registers the derived pktmover class,
-// and allocates one on request.
-//
-class bx_linux_locator_c : public eth_locator_c {
-public:
- bx_linux_locator_c(void) : eth_locator_c("linux") {}
-protected:
- eth_pktmover_c *allocate(const char *netif,
- const char *macaddr,
- eth_rx_handler_t rxh,
- void *rxarg) {
- return (new bx_linux_pktmover_c(netif, macaddr, rxh, rxarg));
- }
-} bx_linux_match;
-
-
-//
-// Define the methods for the bx_linux_pktmover derived class
-//
-
-// the constructor
-//
-bx_linux_pktmover_c::bx_linux_pktmover_c(const char *netif,
- const char *macaddr,
- eth_rx_handler_t rxh,
- void *rxarg)
-{
- struct sockaddr_ll sll;
- struct packet_mreq mr;
- struct ifreq ifr;
- struct sock_fprog fp;
-
- memcpy(linux_macaddr, macaddr, 6);
-
- // Open packet socket
- //
- if ((this->fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL))) == -1) {
- if (errno == EACCES)
- BX_PANIC(("eth_linux: must be root or have CAP_NET_RAW capability to open socket"));
- else
- BX_PANIC(("eth_linux: could not open socket: %s", strerror(errno)));
- this->fd = -1;
- return;
- }
-
- // Translate interface name to index
- //
- memset(&ifr, 0, sizeof(ifr));
- strcpy(ifr.ifr_name, netif);
- if (ioctl(this->fd, SIOCGIFINDEX, &ifr) == -1) {
- BX_PANIC(("eth_linux: could not get index for interface '%s'\n", netif));
- close(fd);
- this->fd = -1;
- return;
- }
- this->ifindex = ifr.ifr_ifindex;
-
-
- // Bind to given interface
- //
- memset(&sll, 0, sizeof(sll));
- sll.sll_family = AF_PACKET;
- sll.sll_ifindex = this->ifindex;
- if (bind(fd, (struct sockaddr *)&sll, (socklen_t)sizeof(sll)) == -1) {
- BX_PANIC(("eth_linux: could not bind to interface '%s': %s\n", netif, strerror(errno)));
- close(fd);
- this->fd = -1;
- return;
- }
-
- // Put the device into promisc mode.
- //
- memset(&mr, 0, sizeof(mr));
- mr.mr_ifindex = this->ifindex;
- mr.mr_type = PACKET_MR_PROMISC;
- if (setsockopt(this->fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, (void *)&mr, (socklen_t)sizeof(mr)) == -1) {
- BX_PANIC(("eth_linux: could not enable promisc mode: %s\n", strerror(errno)));
- close(this->fd);
- this->fd = -1;
- return;
- }
-
- // Set up non-blocking i/o
- if (fcntl(this->fd, F_SETFL, O_NONBLOCK) == -1) {
- BX_PANIC(("eth_linux: could not set non-blocking i/o on socket"));
- close(this->fd);
- this->fd = -1;
- return;
- }
-
- // Install a filter
-#ifdef notdef
- memcpy(&this->filter, promiscfilter, sizeof(promiscfilter));
- fp.len = 1;
-#endif
- memcpy(&this->filter, macfilter, sizeof(macfilter));
- this->filter[1].k = (macaddr[2] & 0xff) << 24 | (macaddr[3] & 0xff) << 16 |
- (macaddr[4] & 0xff) << 8 | (macaddr[5] & 0xff);
- this->filter[3].k = (macaddr[0] & 0xff) << 8 | (macaddr[1] & 0xff);
- fp.len = BX_LSF_ICNT;
- fp.filter = this->filter;
- BX_INFO(("eth_linux: fp.len=%d fp.filter=%lx", fp.len, (unsigned long) fp.filter));
- if (setsockopt(this->fd, SOL_SOCKET, SO_ATTACH_FILTER, &fp, sizeof(fp)) < 0) {
- BX_PANIC(("eth_linux: could not set socket filter: %s", strerror(errno)));
- close(this->fd);
- this->fd = -1;
- return;
- }
-
- // Start the rx poll
- this->rx_timer_index =
- bx_pc_system.register_timer(this, this->rx_timer_handler, BX_PACKET_POLL,
- 1, 1, "eth_linux"); // continuous, active
-
- this->rxh = rxh;
- this->rxarg = rxarg;
- BX_INFO(("eth_linux: enabled NE2K emulation on interface %s", netif));
-}
-
-// the output routine - called with pre-formatted ethernet frame.
-void
-bx_linux_pktmover_c::sendpkt(void *buf, unsigned io_len)
-{
- int status;
-
- if (this->fd != -1) {
- status = write(this->fd, buf, io_len);
- if (status == -1)
- BX_INFO(("eth_linux: write failed: %s", strerror(errno)));
- }
-}
-
-// The receive poll process
-void
-bx_linux_pktmover_c::rx_timer_handler(void *this_ptr)
-{
- bx_linux_pktmover_c *class_ptr = (bx_linux_pktmover_c *) this_ptr;
-
- class_ptr->rx_timer();
-}
-
-void
-bx_linux_pktmover_c::rx_timer(void)
-{
- int nbytes = 0;
- Bit8u rxbuf[BX_PACKET_BUFSIZ];
- struct sockaddr_ll sll;
- socklen_t fromlen;
-//static unsigned char bcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
-
- if (this->fd == -1)
- return;
-
- fromlen = sizeof(sll);
- nbytes = recvfrom(this->fd, rxbuf, sizeof(rxbuf), 0, (struct sockaddr *)&sll, &fromlen);
-
- if (nbytes == -1) {
- if (errno != EAGAIN)
- BX_INFO(("eth_linux: error receiving packet: %s\n", strerror(errno)));
- return;
- }
-
- // this should be done with LSF someday
- // filter out packets sourced by us
- if (memcmp(sll.sll_addr, this->linux_macaddr, 6) == 0)
- return;
- // let through broadcast, multicast, and our mac address
-// if ((memcmp(rxbuf, bcast_addr, 6) == 0) || (memcmp(rxbuf, this->linux_macaddr, 6) == 0) || rxbuf[0] & 0x01) {
- BX_DEBUG(("eth_linux: got packet: %d bytes, dst=%x:%x:%x:%x:%x:%x, src=%x:%x:%x:%x:%x:%x\n", nbytes, rxbuf[0], rxbuf[1], rxbuf[2], rxbuf[3], rxbuf[4], rxbuf[5], rxbuf[6], rxbuf[7], rxbuf[8], rxbuf[9], rxbuf[10], rxbuf[11]));
- (*rxh)(rxarg, rxbuf, nbytes);
-// }
-}
-#endif /* if BX_NE2K_SUPPORT && defined ETH_LINUX */
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: eth_null.cc,v 1.13 2002/11/20 19:06:23 bdenney Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2001 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-// eth_null.cc - skeleton code for an ethernet pktmover
-
-// Various networking docs:
-// http://www.graphcomp.com/info/rfc/
-// rfc0826: arp
-// rfc0903: rarp
-
-// Define BX_PLUGGABLE in files that can be compiled into plugins. For
-// platforms that require a special tag on exported symbols, BX_PLUGGABLE
-// is used to know when we are exporting symbols and when we are importing.
-#define BX_PLUGGABLE
-
-#include "bochs.h"
-#if BX_NE2K_SUPPORT
-
-#define LOG_THIS bx_devices.pluginNE2kDevice->
-
-
-//
-// Define the class. This is private to this module
-//
-class bx_null_pktmover_c : public eth_pktmover_c {
-public:
- bx_null_pktmover_c(const char *netif, const char *macaddr,
- eth_rx_handler_t rxh,
- void *rxarg);
- void sendpkt(void *buf, unsigned io_len);
-private:
- int rx_timer_index;
- static void rx_timer_handler(void *);
- FILE *txlog, *txlog_txt, *rxlog, *rxlog_txt;
-};
-
-
-//
-// Define the static class that registers the derived pktmover class,
-// and allocates one on request.
-//
-class bx_null_locator_c : public eth_locator_c {
-public:
- bx_null_locator_c(void) : eth_locator_c("null") {}
-protected:
- eth_pktmover_c *allocate(const char *netif, const char *macaddr,
- eth_rx_handler_t rxh,
- void *rxarg) {
- return (new bx_null_pktmover_c(netif, macaddr, rxh, rxarg));
- }
-} bx_null_match;
-
-
-//
-// Define the methods for the bx_null_pktmover derived class
-//
-
-// the constructor
-bx_null_pktmover_c::bx_null_pktmover_c(const char *netif,
- const char *macaddr,
- eth_rx_handler_t rxh,
- void *rxarg)
-{
-#if BX_ETH_NULL_LOGGING
- // Start the rx poll
- this->rx_timer_index =
- bx_pc_system.register_timer(this, this->rx_timer_handler, 1000,
- 1, 1, "eth_null"); // continuous, active
- this->rxh = rxh;
- this->rxarg = rxarg;
- // eventually Bryce wants txlog to dump in pcap format so that
- // tcpdump -r FILE can read it and interpret packets.
- txlog = fopen ("ne2k-tx.log", "wb");
- if (!txlog) BX_PANIC (("open ne2k-tx.log failed"));
- txlog_txt = fopen ("ne2k-txdump.txt", "wb");
- if (!txlog_txt) BX_PANIC (("open ne2k-txdump.txt failed"));
- fprintf (txlog_txt, "null packetmover readable log file\n");
- fprintf (txlog_txt, "net IF = %s\n", netif);
- fprintf (txlog_txt, "MAC address = ");
- for (int i=0; i<6; i++)
- fprintf (txlog_txt, "%02x%s", 0xff & macaddr[i], i<5?":" : "");
- fprintf (txlog_txt, "\n--\n");
- fflush (txlog_txt);
-#endif
-}
-
-void
-bx_null_pktmover_c::sendpkt(void *buf, unsigned io_len)
-{
-#if BX_ETH_NULL_LOGGING
- BX_DEBUG (("sendpkt length %u", io_len));
- // dump raw bytes to a file, eventually dump in pcap format so that
- // tcpdump -r FILE can interpret them for us.
- unsigned int n = fwrite (buf, io_len, 1, txlog);
- if (n != 1) BX_ERROR (("fwrite to txlog failed, io_len = %u", io_len));
- // dump packet in hex into an ascii log file
- fprintf (txlog_txt, "NE2K transmitting a packet, length %u\n", io_len);
- Bit8u *charbuf = (Bit8u *)buf;
- for (n=0; n<io_len; n++) {
- if (((n % 16) == 0) && n>0)
- fprintf (txlog_txt, "\n");
- fprintf (txlog_txt, "%02x ", charbuf[n]);
- }
- fprintf (txlog_txt, "\n--\n");
- // flush log so that we see the packets as they arrive w/o buffering
- fflush (txlog);
- fflush (txlog_txt);
-#endif
-}
-
-void bx_null_pktmover_c::rx_timer_handler (void *this_ptr)
-{
-#if BX_ETH_NULL_LOGGING
- /// hey wait there is no receive data with a NULL ethernet, is there....
-
- int io_len = 0;
- Bit8u buf[1];
- bx_null_pktmover_c *class_ptr = (bx_null_pktmover_c *) this_ptr;
- if (io_len > 0) {
- BX_DEBUG (("receive packet length %u", io_len));
- // dump raw bytes to a file, eventually dump in pcap format so that
- // tcpdump -r FILE can interpret them for us.
- int n = fwrite (buf, io_len, 1, class_ptr->rxlog);
- if (n != 1) BX_ERROR (("fwrite to rxlog failed, io_len = %u", io_len));
- // dump packet in hex into an ascii log file
- fprintf (class_ptr->rxlog_txt, "NE2K transmitting a packet, length %u\n", io_len);
- Bit8u *charbuf = (Bit8u *)buf;
- for (n=0; n<io_len; n++) {
- if (((n % 16) == 0) && n>0)
- fprintf (class_ptr->rxlog_txt, "\n");
- fprintf (class_ptr->rxlog_txt, "%02x ", charbuf[n]);
- }
- fprintf (class_ptr->rxlog_txt, "\n--\n");
- // flush log so that we see the packets as they arrive w/o buffering
- fflush (class_ptr->rxlog);
- fflush (class_ptr->rxlog_txt);
- }
-#endif
-}
-
-#endif /* if BX_NE2K_SUPPORT */
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: eth_packetmaker.cc,v 1.8 2002/11/20 19:06:23 bdenney Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Define BX_PLUGGABLE in files that can be compiled into plugins. For
-// platforms that require a special tag on exported symbols, BX_PLUGGABLE
-// is used to know when we are exporting symbols and when we are importing.
-#define BX_PLUGGABLE
-
-#include "bochs.h"
-
-#if BX_NE2K_SUPPORT && defined(ETH_ARPBACK)
-
-#include "eth_packetmaker.h"
-
-
-bx_bool sendable(const eth_packet& outpacket) {
- //FINISH ME!
-}
-
-Bit32u eth_IPmaker::datalen(const eth_packet& outpacket) {
- Bit32u out;
- out=((outpacket.buf[16]<<8)+outpacket.buf[17])-(4*(0xF & outpacket.buf[14]));
- return out;
-}
-
-const Bit8u * eth_IPmaker::datagram(const eth_packet& outpacket) {
- const Bit8u * out;
- out=outpacket.buf+14+(4*(0xF & outpacket.buf[14]));
- return out;
-}
-
-Bit32u eth_IPmaker::build_packet_header(Bit32u source, Bit32u dest, Bit8u protocol, Bit32u datalen) {
- Bit32u temp;
- Bit32u i;
- memcpy(pending.buf,internal_mac,6);
- memcpy(pending.buf+6,external_mac,6);
- memcpy(pending.buf+12,ethtype_ip,2);
- pending.buf[14]=0x45;
- pending.buf[15]=0;
- temp=datalen+20;
- pending.buf[16]=(temp>>8) & 0xFF;
- pending.buf[17]=temp & 0xFF;
- pending.buf[18]=0;
- pending.buf[19]=0;
- pending.buf[20]=0;
- pending.buf[21]=0;
- pending.buf[22]=30;
- pending.buf[23]=protocol;
- pending.buf[24]=0;
- pending.buf[25]=0;
- pending.buf[26]=(source>>24) & 0xFF;
- pending.buf[27]=(source>>16) & 0xFF;
- pending.buf[28]=(source>>8) & 0xFF;
- pending.buf[29]=(source) & 0xFF;
- pending.buf[30]=(dest>>24) & 0xFF;
- pending.buf[31]=(dest>>16) & 0xFF;
- pending.buf[32]=(dest>>8) & 0xFF;
- pending.buf[33]=(dest) & 0xFF;
- //Compute Checksum
- temp=0;
- for(i=14;i<34;i=i+2) {
- Bit32u addee=pending.buf[i];
- addee=(addee<<8) & pending.buf[i+1];
- temp=temp+addee;
- }
- temp=(temp>>16)+(temp&0xFFFF);
- temp=(temp>>16)+(temp&0xFFFF);
- pending.buf[24]=~(Bit8u)((temp>>8) & 0xFF);
- pending.buf[25]=~(Bit8u)(temp & 0xFF);
- return(34);
-}
-
-Bit8u eth_IPmaker::protocol(const eth_packet& outpacket) {
- Bit8u out;
- out=0xFF & *(outpacket.buf+23);
-}
-
-Bit32u eth_IPmaker::source(const eth_packet& outpacket) {
- Bit32u out;
- out=0xFF & *(outpacket.buf+26);
- out=(out<<8) | (0xFF & *(outpacket.buf+27));
- out=(out<<8) | (0xFF & *(outpacket.buf+28));
- out=(out<<8) | (0xFF & *(outpacket.buf+29));
- return out;
-}
-
-Bit32u eth_IPmaker::destination(const eth_packet& outpacket) {
- Bit32u out;
- out=0xFF & *(outpacket.buf+30);
- out=(out<<8) | (0xFF & *(outpacket.buf+31));
- out=(out<<8) | (0xFF & *(outpacket.buf+32));
- out=(out<<8) | (0xFF & *(outpacket.buf+33));
- return out;
-}
-
-void eth_IPmaker::init(void) {
- is_pending=0;
-}
-
-void
-eth_ETHmaker::init(void) {
- arper.init();
-}
-
-bx_bool
-eth_ETHmaker::getpacket(eth_packet& inpacket) {
- return arper.getpacket(inpacket);
-}
-
-bx_bool
-eth_ETHmaker::ishandler(const eth_packet& outpacket) {
- if((outpacket.len>=60) &&
- ( (!memcmp(outpacket.buf, external_mac, 6))
- || (!memcmp(outpacket.buf, broadcast_mac, 6)) ) &&
- ( (!memcmp(outpacket.buf+12, ethtype_arp, 2)) ||
- (!memcmp(outpacket.buf+12, ethtype_ip, 2)) ) &&
- (outpacket.len<PACKET_BUF_SIZE)
- ) {
- return 1;
- }
- return 0;
-}
-
-bx_bool
-eth_ETHmaker::sendpacket(const eth_packet& outpacket) {
- return arper.sendpacket(outpacket);
-}
-
-
-
-void
-eth_ARPmaker::init(void) {
- is_pending=0;
- pending.len=0;
-}
-
-bx_bool
-eth_ARPmaker::getpacket(eth_packet& inpacket) {
- if(is_pending) {
- memcpy(inpacket.buf,pending.buf,pending.len);
- inpacket.len=pending.len;
- is_pending=0;
- return 1;
- }
- return 0;
-}
-
-bx_bool
-eth_ARPmaker::ishandler(const eth_packet& outpacket) {
- if((outpacket.len>=60) &&
- (!memcmp(outpacket.buf+12, ethtype_arp, 2)) &&
- (outpacket.len<PACKET_BUF_SIZE) &&
- ( (!memcmp(outpacket.buf, external_mac, 6))
- || (!memcmp(outpacket.buf, broadcast_mac, 6)) ) &&
- (!memcmp(outpacket.buf+38, external_ip, 4))
- ) {
- return 1;
- }
- return 0;
-}
-
-bx_bool
-eth_ARPmaker::sendpacket(const eth_packet& outpacket) {
- if(is_pending || !ishandler(outpacket)) {
- return 0;
- } else {
- Bit32u tempcrc;
- memcpy(pending.buf,outpacket.buf,outpacket.len); //move to temporary buffer
- memcpy(pending.buf, pending.buf+6, 6); //set destination to sender
- memcpy(pending.buf+6, external_mac, 6); //set sender to us
- memcpy(pending.buf+32, pending.buf+22, 10); //move destination to sender
- memcpy(pending.buf+22, external_mac, 6); //set sender to us
- memcpy(pending.buf+28, external_ip, 4); //set sender to us
- pending.buf[21]=2; //make this a reply and not a request
- //tempcrc=mycrc.get_CRC(pending.buf,len);
- //memcpy(pending.buf+len, &tempcrc, 4);
- pending.len=outpacket.len; //+4
- is_pending=1;
- return 1;
- }
-}
-
-#endif /* if BX_NE2K_SUPPORT && defined(ETH_ARPBACK) */
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: eth_packetmaker.h,v 1.6 2002/10/25 11:44:39 bdenney Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-
-#ifndef _ETH_PACKETMAKER_H_
-#define _ETH_PACKETMAKER_H_
-
-#include "../config.h"
-
-#ifdef ETH_ARPBACK
-
-#define PACKET_BUF_SIZE 2048
-static const Bit8u internal_mac[]={0xB0, 0xC4, 0x20, 0x20, 0x00, 0x00, 0x00};
-static const Bit8u external_mac[]={0xB0, 0xC4, 0x20, 0x20, 0x00, 0x00, 0x00};
-static const Bit8u external_ip[]={ 192, 168, 0, 2, 0x00 };
-static const Bit8u broadcast_mac[]={0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00};
-static const Bit8u ethtype_arp[]={0x08, 0x06, 0x00};
-static const Bit8u ethtype_ip[]={0x08, 0x00, 0x00};
-static const Bit8u prot_udp=17;
-static const Bit8u prot_tcp=6;
-
-
-class eth_packet {
-public:
- Bit8u buf[PACKET_BUF_SIZE];
- Bit32u len;
-};
-
-
-class eth_packetmaker {
-public:
- virtual bx_bool getpacket(eth_packet& inpacket) = 0;
- virtual bx_bool ishandler(const eth_packet& outpacket) = 0;
- virtual bx_bool sendpacket(const eth_packet& outpacket) = 0;
-};
-
-
-class eth_ARPmaker : public eth_packetmaker {
-public:
- void init(void);
- bx_bool ishandler(const eth_packet& outpacket);
- bx_bool sendpacket(const eth_packet& outpacket);
- bx_bool getpacket(eth_packet& inpacket);
-private:
- eth_packet pending;
- bx_bool is_pending;
-};
-
-
-class eth_IPmaker : eth_packetmaker {
-public:
- void init(void);
- virtual bx_bool ishandler(const eth_packet& outpacket)=0;
- virtual bx_bool sendpacket(const eth_packet& outpacket)=0;
- virtual bx_bool getpacket(eth_packet& inpacket)=0;
-
-protected:
- bx_bool sendable(const eth_packet& outpacket);
-
- Bit32u source(const eth_packet& outpacket);
- Bit32u destination(const eth_packet& outpacket);
- Bit8u protocol(const eth_packet& outpacket);
-
- const Bit8u * datagram(const eth_packet& outpacket);
- Bit32u datalen(const eth_packet& outpacket);
-
- //Build a header in pending, return header length in bytes.
- Bit32u build_packet_header(Bit32u source, Bit32u dest, Bit8u protocol, Bit32u datalen);
-
- eth_packet pending;
- bx_bool is_pending;
-
- //Bit8u Version; //=4 (4 bits)
- //It better be!
-
- //Bit8u IHL; //Header length in 32-bit bytes (4 bits)
- //Used to strip layer
-
- //Bit8u Type_of_Service; //not relevent, set to 0;
- //Ignore on receive, set to 0 on send.
-
- //Bit16u Total_Length;//length of the datagram in octets. use 576 or less;
- //Use 576 or less on send.
- //Use to get length on receive
-
- //Bit16u Identification;//Identifier for assembling fragments
- //Ignore, we'll drop fragments
-
- //Bit8u Flags;//0,Don't fragment, More Fragments (vs last fragment)
- //Set to 0 on send
- //Drop if more fragments set.
-
- //Bit16u Fragment Offset;//where in the datagram this fragment belongs
- //Should be 0 for send and receive.
-
- //Bit8u TTL;//Set to something sorta big.
- //Shouldn't be 0 on receive
- //Set to something big on send
-
- //Bit8u Protocol;
- //Defines Protocol.
- //TCP=?, UDP=?
-
- //Bit16u Header_Checksum;//16-bit one's complement of the one's complement
- //sum of all 16-bit words in header;
- //Could check on receive, must set on send.
-
- //Bit32u Source;//source address
- //Bit32u Destination;//destination address
-};
-
-/*
-class eth_TCPmaker : eth_packetmaker {
-};
-
-class eth_UDPmaker : eth_packetmaker {
-};
-*/
-
-class eth_ETHmaker : public eth_packetmaker {
-public:
- //handles all packets to a MAC addr.
- void init(void);
- virtual bx_bool getpacket(eth_packet& inpacket);
- virtual bx_bool ishandler(const eth_packet& outpacket);
- virtual bx_bool sendpacket(const eth_packet& outpacket);
-private:
- eth_ARPmaker arper;
-};
-
-
-#endif // ETH_ARPBACK
-#endif // _ETH_PACKETMAKER_H_
-
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: eth_tap.cc,v 1.16 2003/10/02 11:33:41 danielg4 Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2001 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-// eth_tap.cc - TAP interface by Bryce Denney
-//
-// Here's how to get this working. On the host machine:
-// $ su root
-// # /sbin/insmod ethertap
-// Using /lib/modules/2.2.14-5.0/net/ethertap.o
-// # mknod /dev/tap0 c 36 16 # if not already there
-// # /sbin/ifconfig tap0 10.0.0.1
-// # /sbin/route add -host 10.0.0.2 gw 10.0.0.1
-//
-// Now you have a tap0 device which you can on the ifconfig output. The
-// tap0 interface has the IP address of 10.0.0.1. The bochs machine will have
-// the IP address 10.0.0.2.
-//
-// Compile a bochs version from March 8, 2002 or later with --enable-ne2000.
-// Add this ne2k line to your .bochsrc to activate the tap device.
-// ne2k: ioaddr=0x280, irq=9, mac=fe:fd:00:00:00:01, ethmod=tap, ethdev=tap0
-// Don't change the mac or ethmod!
-//
-// Boot up DLX Linux in Bochs. Log in as root and then type the following
-// commands to set up networking:
-// # ifconfig eth0 10.0.0.2
-// # route add -net 10.0.0.0
-// # route add default gw 10.0.0.1
-// Now you should be able to ping from guest OS to your host machine, if
-// you give its IP number. I'm still having trouble with pings from the
-// host machine to the guest, so something is still not right. Symptoms: I
-// ping from the host to the guest's IP address 10.0.0.2. With tcpdump I can
-// see the ping going to Bochs, and then the ping reply coming from Bochs.
-// But the ping program itself does not see the responses....well every
-// once in a while it does, like 1 in 60 pings.
-//
-// host$ ping 10.0.0.2
-// PING 10.0.0.2 (10.0.0.2) from 10.0.0.1 : 56(84) bytes of data.
-//
-// Netstat output:
-// 20:29:59.018776 fe:fd:0:0:0:0 fe:fd:0:0:0:1 0800 98: 10.0.0.1 > 10.0.0.2: icmp: echo request
-// 4500 0054 2800 0000 4001 3ea7 0a00 0001
-// 0a00 0002 0800 09d3 a53e 0400 9765 893c
-// 3949 0000 0809 0a0b 0c0d 0e0f 1011 1213
-// 1415 1617 1819
-// 20:29:59.023017 fe:fd:0:0:0:1 fe:fd:0:0:0:0 0800 98: 10.0.0.2 > 10.0.0.1: icmp: echo reply
-// 4500 0054 004a 0000 4001 665d 0a00 0002
-// 0a00 0001 0000 11d3 a53e 0400 9765 893c
-// 3949 0000 0809 0a0b 0c0d 0e0f 1011 1213
-// 1415 1617 1819
-//
-// I suspect it may be related to the fact that ping 10.0.0.1 from the
-// host also doesn't work. Why wouldn't the host respond to its own IP
-// address on the tap0 device?
-//
-// Theoretically, if you set up packet forwarding (with masquerading) on the
-// host, you should be able to get Bochs talking to anyone on the internet.
-//
-
-// Define BX_PLUGGABLE in files that can be compiled into plugins. For
-// platforms that require a special tag on exported symbols, BX_PLUGGABLE
-// is used to know when we are exporting symbols and when we are importing.
-#define BX_PLUGGABLE
-
-#include "bochs.h"
-#if BX_NE2K_SUPPORT
-
-#define LOG_THIS bx_devices.pluginNE2kDevice->
-
-#include <signal.h>
-#include <sys/param.h>
-#include <sys/ioctl.h>
-#ifndef __APPLE__
-#include <sys/poll.h>
-#endif
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <sys/socket.h>
-#include <sys/uio.h>
-#include <sys/wait.h>
-#if defined(__FreeBSD__) || defined(__APPLE__) // Should be fixed for other *BSD
-#include <net/if.h>
-#else
-#include <asm/types.h>
-#include <linux/netlink.h>
-#include <linux/if.h>
-#endif
-#include <assert.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#define TAP_VIRTUAL_HW_ADDR 0xDEADBEEF
-#define BX_ETH_TAP_LOGGING 1
-#define BX_PACKET_BUFSIZ 2048 // Enough for an ether frame
-
-//
-// Define the class. This is private to this module
-//
-class bx_tap_pktmover_c : public eth_pktmover_c {
-public:
- bx_tap_pktmover_c(const char *netif, const char *macaddr,
- eth_rx_handler_t rxh,
- void *rxarg);
- void sendpkt(void *buf, unsigned io_len);
-private:
- int fd;
- int rx_timer_index;
- static void rx_timer_handler(void *);
- void rx_timer ();
- FILE *txlog, *txlog_txt, *rxlog, *rxlog_txt;
-};
-
-
-//
-// Define the static class that registers the derived pktmover class,
-// and allocates one on request.
-//
-class bx_tap_locator_c : public eth_locator_c {
-public:
- bx_tap_locator_c(void) : eth_locator_c("tap") {}
-protected:
- eth_pktmover_c *allocate(const char *netif, const char *macaddr,
- eth_rx_handler_t rxh,
- void *rxarg) {
- return (new bx_tap_pktmover_c(netif, macaddr, rxh, rxarg));
- }
-} bx_tap_match;
-
-
-//
-// Define the methods for the bx_tap_pktmover derived class
-//
-
-// the constructor
-bx_tap_pktmover_c::bx_tap_pktmover_c(const char *netif,
- const char *macaddr,
- eth_rx_handler_t rxh,
- void *rxarg)
-{
- int flags;
- char filename[BX_PATHNAME_LEN];
- if (strncmp (netif, "tap", 3) != 0) {
- BX_PANIC (("eth_tap: interface name (%s) must be tap0..tap15", netif));
- }
- sprintf (filename, "/dev/%s", netif);
-
-#if defined(__linux__)
- // check if the TAP devices is running, and turn on ARP. This is based
- // on code from the Mac-On-Linux project. http://http://www.maconlinux.org/
- int sock = socket( AF_INET, SOCK_DGRAM, 0 );
- if (sock < 0) {
- BX_PANIC (("socket creation: %s", strerror(errno)));
- return;
- }
- struct ifreq ifr;
- memset( &ifr, 0, sizeof(ifr) );
- strncpy( ifr.ifr_name, netif, sizeof(ifr.ifr_name) );
- if( ioctl( sock, SIOCGIFFLAGS, &ifr ) < 0 ){
- BX_PANIC (("SIOCGIFFLAGS on %s: %s", netif, strerror (errno)));
- close(sock);
- return;
- }
- if( !(ifr.ifr_flags & IFF_RUNNING ) ){
- BX_PANIC (("%s device is not running", netif));
- close(sock);
- return;
- }
- if( (ifr.ifr_flags & IFF_NOARP ) ){
- BX_INFO (("turn on ARP for %s device", netif));
- ifr.ifr_flags &= ~IFF_NOARP;
- if( ioctl( sock, SIOCSIFFLAGS, &ifr ) < 0 ) {
- BX_PANIC (("SIOCSIFFLAGS: %s", strerror(errno)));
- close(sock);
- return;
- }
- }
- close(sock);
-#endif
-
- fd = open (filename, O_RDWR);
- if (fd < 0) {
- BX_PANIC (("open failed on %s: %s", netif, strerror (errno)));
- return;
- }
-
- /* set O_ASYNC flag so that we can poll with read() */
- if ((flags = fcntl( fd, F_GETFL)) < 0) {
- BX_PANIC (("getflags on tap device: %s", strerror (errno)));
- }
- flags |= O_NONBLOCK;
- if (fcntl( fd, F_SETFL, flags ) < 0) {
- BX_PANIC (("set tap device flags: %s", strerror (errno)));
- }
-
- BX_INFO (("eth_tap: opened %s device", netif));
-
- /* Execute the configuration script */
- char intname[IFNAMSIZ];
- strcpy(intname,netif);
- char *scriptname=bx_options.ne2k.Oscript->getptr();
- if((scriptname != NULL)
- &&(strcmp(scriptname, "") != 0)
- &&(strcmp(scriptname, "none") != 0)) {
- if (execute_script(scriptname, intname) < 0)
- BX_ERROR (("execute script '%s' on %s failed", scriptname, intname));
- }
-
- // Start the rx poll
- this->rx_timer_index =
- bx_pc_system.register_timer(this, this->rx_timer_handler, 1000,
- 1, 1, "eth_tap"); // continuous, active
- this->rxh = rxh;
- this->rxarg = rxarg;
-#if BX_ETH_TAP_LOGGING
- // eventually Bryce wants txlog to dump in pcap format so that
- // tcpdump -r FILE can read it and interpret packets.
- txlog = fopen ("ne2k-tx.log", "wb");
- if (!txlog) BX_PANIC (("open ne2k-tx.log failed"));
- txlog_txt = fopen ("ne2k-txdump.txt", "wb");
- if (!txlog_txt) BX_PANIC (("open ne2k-txdump.txt failed"));
- fprintf (txlog_txt, "tap packetmover readable log file\n");
- fprintf (txlog_txt, "net IF = %s\n", netif);
- fprintf (txlog_txt, "MAC address = ");
- for (int i=0; i<6; i++)
- fprintf (txlog_txt, "%02x%s", 0xff & macaddr[i], i<5?":" : "");
- fprintf (txlog_txt, "\n--\n");
- fflush (txlog_txt);
-
- rxlog = fopen ("ne2k-rx.log", "wb");
- if (!rxlog) BX_PANIC (("open ne2k-rx.log failed"));
- rxlog_txt = fopen ("ne2k-rxdump.txt", "wb");
- if (!rxlog_txt) BX_PANIC (("open ne2k-rxdump.txt failed"));
- fprintf (rxlog_txt, "tap packetmover readable log file\n");
- fprintf (rxlog_txt, "net IF = %s\n", netif);
- fprintf (rxlog_txt, "MAC address = ");
- for (int i=0; i<6; i++)
- fprintf (rxlog_txt, "%02x%s", 0xff & macaddr[i], i<5?":" : "");
- fprintf (rxlog_txt, "\n--\n");
- fflush (rxlog_txt);
-
-#endif
-}
-
-void
-bx_tap_pktmover_c::sendpkt(void *buf, unsigned io_len)
-{
- Bit8u txbuf[BX_PACKET_BUFSIZ];
- txbuf[0] = 0;
- txbuf[1] = 0;
-#if defined(__FreeBSD__) || defined(__APPLE__) // Should be fixed for other *BSD
- memcpy (txbuf, buf, io_len);
- unsigned int size = write (fd, txbuf, io_len);
- if (size != io_len) {
-#else
- memcpy (txbuf+2, buf, io_len);
- unsigned int size = write (fd, txbuf, io_len+2);
- if (size != io_len+2) {
-#endif
- BX_PANIC (("write on tap device: %s", strerror (errno)));
- } else {
- BX_INFO (("wrote %d bytes + 2 byte pad on tap", io_len));
- }
-#if BX_ETH_TAP_LOGGING
- BX_DEBUG (("sendpkt length %u", io_len));
- // dump raw bytes to a file, eventually dump in pcap format so that
- // tcpdump -r FILE can interpret them for us.
- int n = fwrite (buf, io_len, 1, txlog);
- if (n != 1) BX_ERROR (("fwrite to txlog failed, io_len = %u", io_len));
- // dump packet in hex into an ascii log file
- fprintf (txlog_txt, "NE2K transmitting a packet, length %u\n", io_len);
- Bit8u *charbuf = (Bit8u *)buf;
- for (n=0; n<(int)io_len; n++) {
- if (((n % 16) == 0) && n>0)
- fprintf (txlog_txt, "\n");
- fprintf (txlog_txt, "%02x ", charbuf[n]);
- }
- fprintf (txlog_txt, "\n--\n");
- // flush log so that we see the packets as they arrive w/o buffering
- fflush (txlog);
- fflush (txlog_txt);
-#endif
-}
-
-void bx_tap_pktmover_c::rx_timer_handler (void *this_ptr)
-{
- bx_tap_pktmover_c *class_ptr = (bx_tap_pktmover_c *) this_ptr;
- class_ptr->rx_timer();
-}
-
-void bx_tap_pktmover_c::rx_timer ()
-{
- int nbytes;
- Bit8u buf[BX_PACKET_BUFSIZ];
- Bit8u *rxbuf;
- if (fd<0) return;
- nbytes = read (fd, buf, sizeof(buf));
-
- // hack: discard first two bytes
-#if defined(__FreeBSD__) || defined(__APPLE__) // Should be fixed for other *BSD
- rxbuf = buf;
-#else
- rxbuf = buf+2;
- nbytes-=2;
-#endif
-
- // hack: TAP device likes to create an ethernet header which has
- // the same source and destination address FE:FD:00:00:00:00.
- // Change the dest address to FE:FD:00:00:00:01.
-#if defined(__linux__)
- rxbuf[5] = 1;
-#endif
-
- if (nbytes>0)
- BX_INFO (("tap read returned %d bytes", nbytes));
- if (nbytes<0) {
- if (errno != EAGAIN)
- BX_ERROR (("tap read error: %s", strerror(errno)));
- return;
- }
-#if BX_ETH_TAP_LOGGING
- if (nbytes > 0) {
- BX_DEBUG (("receive packet length %u", nbytes));
- // dump raw bytes to a file, eventually dump in pcap format so that
- // tcpdump -r FILE can interpret them for us.
- int n = fwrite (rxbuf, nbytes, 1, rxlog);
- if (n != 1) BX_ERROR (("fwrite to rxlog failed, nbytes = %d", nbytes));
- // dump packet in hex into an ascii log file
- fprintf (rxlog_txt, "NE2K received a packet, length %u\n", nbytes);
- for (n=0; n<nbytes; n++) {
- if (((n % 16) == 0) && n>0)
- fprintf (rxlog_txt, "\n");
- fprintf (rxlog_txt, "%02x ", rxbuf[n]);
- }
- fprintf (rxlog_txt, "\n--\n");
- // flush log so that we see the packets as they arrive w/o buffering
- fflush (rxlog);
- fflush (rxlog_txt);
- }
-#endif
- BX_DEBUG(("eth_tap: got packet: %d bytes, dst=%x:%x:%x:%x:%x:%x, src=%x:%x:%x:%x:%x:%x\n", nbytes, rxbuf[0], rxbuf[1], rxbuf[2], rxbuf[3], rxbuf[4], rxbuf[5], rxbuf[6], rxbuf[7], rxbuf[8], rxbuf[9], rxbuf[10], rxbuf[11]));
- if (nbytes < 60) {
- BX_INFO (("packet too short (%d), padding to 60", nbytes));
- nbytes = 60;
- }
- (*rxh)(rxarg, rxbuf, nbytes);
-}
-
-#endif /* if BX_NE2K_SUPPORT */
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: eth_tuntap.cc,v 1.9 2003/04/26 14:48:45 cbothamy Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2001 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-// eth_tuntap.cc - TUN/TAP interface by Renzo Davoli <renzo@cs.unibo.it>
-//
-// WARNING: These instructions were written for ethertap, not TUN/TAP.
-//
-// Here's how to get this working. On the host machine:
-// $ su root
-// # /sbin/insmod ethertap
-// Using /lib/modules/2.2.14-5.0/net/ethertap.o
-// # mknod /dev/tap0 c 36 16 # if not already there
-// # /sbin/ifconfig tap0 10.0.0.1
-// # /sbin/route add -host 10.0.0.2 gw 10.0.0.1
-//
-// Now you have a tap0 device which you can on the ifconfig output. The
-// tap0 interface has the IP address of 10.0.0.1. The bochs machine will have
-// the IP address 10.0.0.2.
-//
-// Compile a bochs version from March 8, 2002 or later with --enable-ne2000.
-// Add this ne2k line to your .bochsrc to activate the tap device.
-// ne2k: ioaddr=0x280, irq=9, mac=fe:fd:00:00:00:01, ethmod=tap, ethdev=tap0
-// Don't change the mac or ethmod!
-//
-// Boot up DLX Linux in Bochs. Log in as root and then type the following
-// commands to set up networking:
-// # ifconfig eth0 10.0.0.2
-// # route add -net 10.0.0.0
-// # route add default gw 10.0.0.1
-// Now you should be able to ping from guest OS to your host machine, if
-// you give its IP number. I'm still having trouble with pings from the
-// host machine to the guest, so something is still not right. Symptoms: I
-// ping from the host to the guest's IP address 10.0.0.2. With tcpdump I can
-// see the ping going to Bochs, and then the ping reply coming from Bochs.
-// But the ping program itself does not see the responses....well every
-// once in a while it does, like 1 in 60 pings.
-//
-// host$ ping 10.0.0.2
-// PING 10.0.0.2 (10.0.0.2) from 10.0.0.1 : 56(84) bytes of data.
-//
-// Netstat output:
-// 20:29:59.018776 fe:fd:0:0:0:0 fe:fd:0:0:0:1 0800 98: 10.0.0.1 > 10.0.0.2: icmp: echo request
-// 4500 0054 2800 0000 4001 3ea7 0a00 0001
-// 0a00 0002 0800 09d3 a53e 0400 9765 893c
-// 3949 0000 0809 0a0b 0c0d 0e0f 1011 1213
-// 1415 1617 1819
-// 20:29:59.023017 fe:fd:0:0:0:1 fe:fd:0:0:0:0 0800 98: 10.0.0.2 > 10.0.0.1: icmp: echo reply
-// 4500 0054 004a 0000 4001 665d 0a00 0002
-// 0a00 0001 0000 11d3 a53e 0400 9765 893c
-// 3949 0000 0809 0a0b 0c0d 0e0f 1011 1213
-// 1415 1617 1819
-//
-// I suspect it may be related to the fact that ping 10.0.0.1 from the
-// host also doesn't work. Why wouldn't the host respond to its own IP
-// address on the tap0 device?
-//
-// Theoretically, if you set up packet forwarding (with masquerading) on the
-// host, you should be able to get Bochs talking to anyone on the internet.
-//
-
-// Define BX_PLUGGABLE in files that can be compiled into plugins. For
-// platforms that require a special tag on exported symbols, BX_PLUGGABLE
-// is used to know when we are exporting symbols and when we are importing.
-#define BX_PLUGGABLE
-
-#include "bochs.h"
-#if BX_NE2K_SUPPORT
-
-#define LOG_THIS bx_devices.pluginNE2kDevice->
-
-#include <signal.h>
-#include <sys/param.h>
-#include <sys/ioctl.h>
-#include <sys/poll.h>
-#include <sys/time.h>
-#include <sys/resource.h>
-#include <asm/types.h>
-#include <sys/socket.h>
-#include <sys/uio.h>
-#include <sys/wait.h>
-#include <linux/netlink.h>
-#include <linux/if.h>
-#include <linux/if_tun.h>
-#include <assert.h>
-#include <fcntl.h>
-#include <errno.h>
-
-#define TUNTAP_VIRTUAL_HW_ADDR 0xDEADBEEF
-#define BX_ETH_TUNTAP_LOGGING 0
-#define BX_PACKET_BUFSIZ 2048 // Enough for an ether frame
-
-int tun_alloc(char *dev);
-
-//
-// Define the class. This is private to this module
-//
-class bx_tuntap_pktmover_c : public eth_pktmover_c {
-public:
- bx_tuntap_pktmover_c(const char *netif, const char *macaddr,
- eth_rx_handler_t rxh,
- void *rxarg);
- void sendpkt(void *buf, unsigned io_len);
-private:
- int fd;
- int rx_timer_index;
- static void rx_timer_handler(void *);
- void rx_timer ();
- FILE *txlog, *txlog_txt, *rxlog, *rxlog_txt;
-};
-
-
-//
-// Define the static class that registers the derived pktmover class,
-// and allocates one on request.
-//
-class bx_tuntap_locator_c : public eth_locator_c {
-public:
- bx_tuntap_locator_c(void) : eth_locator_c("tuntap") {}
-protected:
- eth_pktmover_c *allocate(const char *netif, const char *macaddr,
- eth_rx_handler_t rxh,
- void *rxarg) {
- return (new bx_tuntap_pktmover_c(netif, macaddr, rxh, rxarg));
- }
-} bx_tuntap_match;
-
-
-//
-// Define the methods for the bx_tuntap_pktmover derived class
-//
-
-// the constructor
-bx_tuntap_pktmover_c::bx_tuntap_pktmover_c(const char *netif,
- const char *macaddr,
- eth_rx_handler_t rxh,
- void *rxarg)
-{
- int flags;
- if (strncmp (netif, "tun", 3) != 0) {
- BX_PANIC (("eth_tuntap: interface name (%s) must be tun", netif));
- }
-#ifdef NEVERDEF
- char filename[BX_PATHNAME_LEN];
- sprintf (filename, "/dev/net/%s", netif);
-
- // check if the TUN/TAP devices is running, and turn on ARP. This is based
- // on code from the Mac-On-Linux project. http://http://www.maconlinux.org/
- int sock = socket( AF_INET, SOCK_DGRAM, 0 );
- if (sock < 0) {
- BX_PANIC (("socket creation: %s", strerror(errno)));
- return;
- }
- struct ifreq ifr;
- memset( &ifr, 0, sizeof(ifr) );
- strncpy( ifr.ifr_name, netif, sizeof(ifr.ifr_name) );
- if( ioctl( sock, SIOCGIFFLAGS, &ifr ) < 0 ){
- BX_PANIC (("SIOCGIFFLAGS on %s: %s", netif, strerror (errno)));
- close(sock);
- return;
- }
- if( !(ifr.ifr_flags & IFF_RUNNING ) ){
- BX_PANIC (("%s device is not running", netif));
- close(sock);
- return;
- }
- if( (ifr.ifr_flags & IFF_NOARP ) ){
- BX_INFO (("turn on ARP for %s device", netif));
- ifr.ifr_flags &= ~IFF_NOARP;
- if( ioctl( sock, SIOCSIFFLAGS, &ifr ) < 0 ) {
- BX_PANIC (("SIOCSIFFLAGS: %s", strerror(errno)));
- close(sock);
- return;
- }
- }
- close(sock);
-
- fd = open (filename, O_RDWR);
-#endif
- char intname[IFNAMSIZ];
- strcpy(intname,netif);
- fd=tun_alloc(intname);
- if (fd < 0) {
- BX_PANIC (("open failed on %s: %s", netif, strerror (errno)));
- return;
- }
-
- /* set O_ASYNC flag so that we can poll with read() */
- if ((flags = fcntl( fd, F_GETFL)) < 0) {
- BX_PANIC (("getflags on tun device: %s", strerror (errno)));
- }
- flags |= O_NONBLOCK;
- if (fcntl( fd, F_SETFL, flags ) < 0) {
- BX_PANIC (("set tun device flags: %s", strerror (errno)));
- }
-
- BX_INFO (("eth_tuntap: opened %s device", netif));
-
- /* Execute the configuration script */
- char *scriptname=bx_options.ne2k.Oscript->getptr();
- if((scriptname != NULL)
- &&(strcmp(scriptname, "") != 0)
- &&(strcmp(scriptname, "none") != 0)) {
- if (execute_script(scriptname, intname) < 0)
- BX_ERROR (("execute script '%s' on %s failed", scriptname, intname));
- }
-
- // Start the rx poll
- this->rx_timer_index =
- bx_pc_system.register_timer(this, this->rx_timer_handler, 1000,
- 1, 1, "eth_tuntap"); // continuous, active
- this->rxh = rxh;
- this->rxarg = rxarg;
-#if BX_ETH_TUNTAP_LOGGING
- // eventually Bryce wants txlog to dump in pcap format so that
- // tcpdump -r FILE can read it and interpret packets.
- txlog = fopen ("ne2k-tx.log", "wb");
- if (!txlog) BX_PANIC (("open ne2k-tx.log failed"));
- txlog_txt = fopen ("ne2k-txdump.txt", "wb");
- if (!txlog_txt) BX_PANIC (("open ne2k-txdump.txt failed"));
- fprintf (txlog_txt, "tuntap packetmover readable log file\n");
- fprintf (txlog_txt, "net IF = %s\n", netif);
- fprintf (txlog_txt, "MAC address = ");
- for (int i=0; i<6; i++)
- fprintf (txlog_txt, "%02x%s", 0xff & macaddr[i], i<5?":" : "");
- fprintf (txlog_txt, "\n--\n");
- fflush (txlog_txt);
-
- rxlog = fopen ("ne2k-rx.log", "wb");
- if (!rxlog) BX_PANIC (("open ne2k-rx.log failed"));
- rxlog_txt = fopen ("ne2k-rxdump.txt", "wb");
- if (!rxlog_txt) BX_PANIC (("open ne2k-rxdump.txt failed"));
- fprintf (rxlog_txt, "tuntap packetmover readable log file\n");
- fprintf (rxlog_txt, "net IF = %s\n", netif);
- fprintf (rxlog_txt, "MAC address = ");
- for (int i=0; i<6; i++)
- fprintf (rxlog_txt, "%02x%s", 0xff & macaddr[i], i<5?":" : "");
- fprintf (rxlog_txt, "\n--\n");
- fflush (rxlog_txt);
-
-#endif
-}
-
-void
-bx_tuntap_pktmover_c::sendpkt(void *buf, unsigned io_len)
-{
-#ifdef NEVERDEF
- Bit8u txbuf[BX_PACKET_BUFSIZ];
- txbuf[0] = 0;
- txbuf[1] = 0;
- memcpy (txbuf+2, buf, io_len);
- unsigned int size = write (fd, txbuf, io_len+2);
- if (size != io_len+2) {
- BX_PANIC (("write on tuntap device: %s", strerror (errno)));
- } else {
- BX_INFO (("wrote %d bytes + 2 byte pad on tuntap", io_len));
- }
-#endif
- unsigned int size = write (fd, buf, io_len);
- if (size != io_len) {
- BX_PANIC (("write on tuntap device: %s", strerror (errno)));
- } else {
- BX_INFO (("wrote %d bytes on tuntap", io_len));
- }
-#if BX_ETH_TUNTAP_LOGGING
- BX_DEBUG (("sendpkt length %u", io_len));
- // dump raw bytes to a file, eventually dump in pcap format so that
- // tcpdump -r FILE can interpret them for us.
- int n = fwrite (buf, io_len, 1, txlog);
- if (n != 1) BX_ERROR (("fwrite to txlog failed", io_len));
- // dump packet in hex into an ascii log file
- fprintf (txlog_txt, "NE2K transmitting a packet, length %u\n", io_len);
- Bit8u *charbuf = (Bit8u *)buf;
- for (n=0; n<io_len; n++) {
- if (((n % 16) == 0) && n>0)
- fprintf (txlog_txt, "\n");
- fprintf (txlog_txt, "%02x ", charbuf[n]);
- }
- fprintf (txlog_txt, "\n--\n");
- // flush log so that we see the packets as they arrive w/o buffering
- fflush (txlog);
- fflush (txlog_txt);
-#endif
-}
-
-void bx_tuntap_pktmover_c::rx_timer_handler (void *this_ptr)
-{
- bx_tuntap_pktmover_c *class_ptr = (bx_tuntap_pktmover_c *) this_ptr;
- class_ptr->rx_timer();
-}
-
-void bx_tuntap_pktmover_c::rx_timer ()
-{
- int nbytes;
- Bit8u buf[BX_PACKET_BUFSIZ];
- Bit8u *rxbuf;
- if (fd<0) return;
- nbytes = read (fd, buf, sizeof(buf));
-
-#ifdef NEVERDEF
- // hack: discard first two bytes
- rxbuf = buf+2;
- nbytes-=2;
-#else
- rxbuf=buf;
-#endif
-
- // hack: TUN/TAP device likes to create an ethernet header which has
- // the same source and destination address FE:FD:00:00:00:00.
- // Change the dest address to FE:FD:00:00:00:01.
- rxbuf[5] = 1;
-
- if (nbytes>0)
- BX_INFO (("tuntap read returned %d bytes", nbytes));
- if (nbytes<0) {
- if (errno != EAGAIN)
- BX_ERROR (("tuntap read error: %s", strerror(errno)));
- return;
- }
-#if BX_ETH_TUNTAP_LOGGING
- if (nbytes > 0) {
- BX_DEBUG (("receive packet length %u", nbytes));
- // dump raw bytes to a file, eventually dump in pcap format so that
- // tcpdump -r FILE can interpret them for us.
- int n = fwrite (rxbuf, nbytes, 1, rxlog);
- if (n != 1) BX_ERROR (("fwrite to rxlog failed", nbytes));
- // dump packet in hex into an ascii log file
- fprintf (rxlog_txt, "NE2K received a packet, length %u\n", nbytes);
- for (n=0; n<nbytes; n++) {
- if (((n % 16) == 0) && n>0)
- fprintf (rxlog_txt, "\n");
- fprintf (rxlog_txt, "%02x ", rxbuf[n]);
- }
- fprintf (rxlog_txt, "\n--\n");
- // flush log so that we see the packets as they arrive w/o buffering
- fflush (rxlog);
- fflush (rxlog_txt);
- }
-#endif
- BX_DEBUG(("eth_tuntap: got packet: %d bytes, dst=%x:%x:%x:%x:%x:%x, src=%x:%x:%x:%x:%x:%x\n", nbytes, rxbuf[0], rxbuf[1], rxbuf[2], rxbuf[3], rxbuf[4], rxbuf[5], rxbuf[6], rxbuf[7], rxbuf[8], rxbuf[9], rxbuf[10], rxbuf[11]));
- if (nbytes < 60) {
- BX_INFO (("packet too short (%d), padding to 60", nbytes));
- nbytes = 60;
- }
- (*rxh)(rxarg, rxbuf, nbytes);
-}
-
-
- int tun_alloc(char *dev)
- {
- struct ifreq ifr;
- int fd, err;
-
- if( (fd = open("/dev/net/tun", O_RDWR)) < 0 )
- return -1;
-
- memset(&ifr, 0, sizeof(ifr));
-
- /* Flags: IFF_TUN - TUN device (no Ethernet headers)
- * IFF_TAP - TAP device
- *
- * IFF_NO_PI - Do not provide packet information
- */
- ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
- if( *dev )
- strncpy(ifr.ifr_name, dev, IFNAMSIZ);
-
- if( (err = ioctl(fd, TUNSETIFF, (void *) &ifr)) < 0 ){
- close(fd);
- return err;
- }
-
- //strcpy(dev, ifr.ifr_name);
- ioctl( fd, TUNSETNOCSUM, 1 );
-
- return fd;
- }
-
-#endif /* if BX_NE2K_SUPPORT */
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: extfpuirq.cc,v 1.5 2003/07/31 12:04:48 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-//
-// External circuit for MSDOS compatible FPU exceptions
-//
-
-// Define BX_PLUGGABLE in files that can be compiled into plugins. For
-// platforms that require a special tag on exported symbols, BX_PLUGGABLE
-// is used to know when we are exporting symbols and when we are importing.
-#define BX_PLUGGABLE
-
-#include "bochs.h"
-
-#define LOG_THIS theExternalFpuIrq->
-
-bx_extfpuirq_c *theExternalFpuIrq = NULL;
-
- int
-libextfpuirq_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[])
-{
- theExternalFpuIrq = new bx_extfpuirq_c ();
- bx_devices.pluginExtFpuIrq = theExternalFpuIrq;
- BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theExternalFpuIrq, BX_PLUGIN_EXTFPUIRQ);
- return(0); // Success
-}
-
- void
-libextfpuirq_LTX_plugin_fini(void)
-{
-}
-
-bx_extfpuirq_c::bx_extfpuirq_c(void)
-{
- put("EFIRQ");
- settype(EXTFPUIRQLOG);
-}
-
-bx_extfpuirq_c::~bx_extfpuirq_c(void)
-{
- // nothing for now
- BX_DEBUG(("Exit."));
-}
-
-
- void
-bx_extfpuirq_c::init(void)
-{
- // called once when bochs initializes
- DEV_register_iowrite_handler(this, write_handler, 0x00F0, "External FPU IRQ", 1);
- DEV_register_irq(13, "External FPU IRQ");
-}
-
- void
-bx_extfpuirq_c::reset(unsigned type)
-{
- // We should handle IGNNE here
- DEV_pic_lower_irq(13);
-}
-
-
- // static IO port write callback handler
- // redirects to non-static class handler to avoid virtual functions
-
- void
-bx_extfpuirq_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len)
-{
-#if !BX_USE_EFI_SMF
- bx_extfpuirq_c *class_ptr = (bx_extfpuirq_c *) this_ptr;
-
- class_ptr->write(address, value, io_len);
-}
-
- void
-bx_extfpuirq_c::write(Bit32u address, Bit32u value, unsigned io_len)
-{
-#else
- UNUSED(this_ptr);
-#endif // !BX_USE_EFI_SMF
-
- // We should handle IGNNE here
- DEV_pic_lower_irq(13);
-}
-
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: extfpuirq.h,v 1.2 2003/01/07 08:17:15 cbothamy Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-#if BX_USE_EFI_SMF
-# define BX_EXTFPUIRQ_SMF static
-# define BX_EXTFPUIRQ_THIS theExternalFpuIrq->
-#else
-# define BX_EXTFPUIRQ_SMF
-# define BX_EXTFPUIRQ_THIS this->
-#endif
-
-
-class bx_extfpuirq_c : public bx_devmodel_c {
-
-public:
- bx_extfpuirq_c(void);
- ~bx_extfpuirq_c(void);
- virtual void init(void);
- virtual void reset(unsigned type);
-
-private:
-
- static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len);
-#if !BX_USE_EFI_SMF
- void write(Bit32u address, Bit32u value, unsigned io_len);
-#endif
- };
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: floppy.cc,v 1.69 2003/12/18 20:04:49 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-//
-//
-// Floppy Disk Controller Docs:
-// Intel 82077A Data sheet
-// ftp://void-core.2y.net/pub/docs/fdc/82077AA_FloppyControllerDatasheet.pdf
-// Intel 82078 Data sheet
-// ftp://download.intel.com/design/periphrl/datashts/29047403.PDF
-// Other FDC references
-// http://debs.future.easyspace.com/Programming/Hardware/FDC/floppy.html
-// And a port list:
-// http://mudlist.eorbit.net/~adam/pickey/ports.html
-//
-
-// Define BX_PLUGGABLE in files that can be compiled into plugins. For
-// platforms that require a special tag on exported symbols, BX_PLUGGABLE
-// is used to know when we are exporting symbols and when we are importing.
-#define BX_PLUGGABLE
-
-
-extern "C" {
-#include <errno.h>
-}
-
-#ifdef __linux__
-extern "C" {
-#include <sys/ioctl.h>
-#include <linux/fd.h>
-}
-#endif
-#include "bochs.h"
-// windows.h included by bochs.h
-#ifdef WIN32
-extern "C" {
-#include <winioctl.h>
-}
-#endif
-#define LOG_THIS theFloppyController->
-
-bx_floppy_ctrl_c *theFloppyController;
-
-/* for main status register */
-#define FD_MS_MRQ 0x80
-#define FD_MS_DIO 0x40
-#define FD_MS_NDMA 0x20
-#define FD_MS_BUSY 0x10
-#define FD_MS_ACTD 0x08
-#define FD_MS_ACTC 0x04
-#define FD_MS_ACTB 0x02
-#define FD_MS_ACTA 0x01
-
-#define FROM_FLOPPY 10
-#define TO_FLOPPY 11
-
-#define FLOPPY_DMA_CHAN 2
-
-typedef struct {
- unsigned id;
- Bit8u trk;
- Bit8u hd;
- Bit8u spt;
- unsigned sectors;
-} floppy_type_t;
-
-static floppy_type_t floppy_type[8] = {
- {BX_FLOPPY_160K, 40, 1, 8, 320},
- {BX_FLOPPY_180K, 40, 1, 9, 360},
- {BX_FLOPPY_320K, 40, 2, 8, 640},
- {BX_FLOPPY_360K, 40, 2, 9, 720},
- {BX_FLOPPY_720K, 80, 2, 9, 1440},
- {BX_FLOPPY_1_2, 80, 2, 15, 2400},
- {BX_FLOPPY_1_44, 80, 2, 18, 2880},
- {BX_FLOPPY_2_88, 80, 2, 36, 5760}
-};
-
-
- int
-libfloppy_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[])
-{
- theFloppyController = new bx_floppy_ctrl_c ();
- bx_devices.pluginFloppyDevice = theFloppyController;
- BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theFloppyController, BX_PLUGIN_FLOPPY);
- return(0); // Success
-}
-
- void
-libfloppy_LTX_plugin_fini(void)
-{
-}
-
-
-bx_floppy_ctrl_c::bx_floppy_ctrl_c(void)
-{
- put("FDD");
- settype(FDLOG);
- s.floppy_timer_index = BX_NULL_TIMER_HANDLE;
-}
-
-bx_floppy_ctrl_c::~bx_floppy_ctrl_c(void)
-{
- // nothing for now
- BX_DEBUG(("Exit."));
-}
-
-
- void
-bx_floppy_ctrl_c::init(void)
-{
- Bit8u i;
-
- BX_DEBUG(("Init $Id: floppy.cc,v 1.69 2003/12/18 20:04:49 vruppert Exp $"));
- DEV_dma_register_8bit_channel(2, dma_read, dma_write, "Floppy Drive");
- DEV_register_irq(6, "Floppy Drive");
- for (unsigned addr=0x03F2; addr<=0x03F7; addr++) {
- DEV_register_ioread_handler(this, read_handler, addr, "Floppy Drive", 1);
- DEV_register_iowrite_handler(this, write_handler, addr, "Floppy Drive", 1);
- }
-
-
- DEV_cmos_set_reg(0x10, 0x00); /* start out with: no drive 0, no drive 1 */
-
- BX_FD_THIS s.num_supported_floppies = 0;
-
- for (i=0; i<4; i++) {
- BX_FD_THIS s.device_type[i] = BX_FLOPPY_NONE;
- BX_FD_THIS s.media[i].type = BX_FLOPPY_NONE;
- }
-
- //
- // Floppy A setup
- //
- BX_FD_THIS s.media[0].sectors_per_track = 0;
- BX_FD_THIS s.media[0].tracks = 0;
- BX_FD_THIS s.media[0].heads = 0;
- BX_FD_THIS s.media[0].sectors = 0;
- BX_FD_THIS s.media[0].fd = -1;
- BX_FD_THIS s.media_present[0] = 0;
- BX_FD_THIS s.device_type[0] = bx_options.floppya.Odevtype->get ();
-
- switch (BX_FD_THIS s.device_type[0]) {
- case BX_FLOPPY_NONE:
- DEV_cmos_set_reg(0x10, (DEV_cmos_get_reg(0x10) & 0x0f) | 0x00);
- break;
- case BX_FLOPPY_360K:
- DEV_cmos_set_reg(0x10, (DEV_cmos_get_reg(0x10) & 0x0f) | 0x10);
- break;
- case BX_FLOPPY_1_2:
- DEV_cmos_set_reg(0x10, (DEV_cmos_get_reg(0x10) & 0x0f) | 0x20);
- break;
- case BX_FLOPPY_720K:
- DEV_cmos_set_reg(0x10, (DEV_cmos_get_reg(0x10) & 0x0f) | 0x30);
- break;
- case BX_FLOPPY_1_44:
- DEV_cmos_set_reg(0x10, (DEV_cmos_get_reg(0x10) & 0x0f) | 0x40);
- break;
- case BX_FLOPPY_2_88:
- DEV_cmos_set_reg(0x10, (DEV_cmos_get_reg(0x10) & 0x0f) | 0x50);
- break;
-
- // use CMOS reserved types
- case BX_FLOPPY_160K:
- DEV_cmos_set_reg(0x10, (DEV_cmos_get_reg(0x10) & 0x0f) | 0x60);
- BX_INFO(("WARNING: 1st floppy uses of reserved CMOS floppy drive type 6"));
- break;
- case BX_FLOPPY_180K:
- DEV_cmos_set_reg(0x10, (DEV_cmos_get_reg(0x10) & 0x0f) | 0x70);
- BX_INFO(("WARNING: 1st floppy uses of reserved CMOS floppy drive type 7"));
- break;
- case BX_FLOPPY_320K:
- DEV_cmos_set_reg(0x10, (DEV_cmos_get_reg(0x10) & 0x0f) | 0x80);
- BX_INFO(("WARNING: 1st floppy uses of reserved CMOS floppy drive type 8"));
- break;
-
- default:
- BX_PANIC(("unknown floppya type"));
- }
- if (BX_FD_THIS s.device_type[0] != BX_FLOPPY_NONE)
- BX_FD_THIS s.num_supported_floppies++;
-
- if (bx_options.floppya.Otype->get () != BX_FLOPPY_NONE) {
- if ( bx_options.floppya.Ostatus->get () == BX_INSERTED) {
- if (evaluate_media(bx_options.floppya.Otype->get (), bx_options.floppya.Opath->getptr (),
- & BX_FD_THIS s.media[0]))
- BX_FD_THIS s.media_present[0] = 1;
- else
- bx_options.floppya.Ostatus->set(BX_EJECTED);
-#define MED (BX_FD_THIS s.media[0])
- BX_INFO(("fd0: '%s' ro=%d, h=%d,t=%d,spt=%d", bx_options.floppya.Opath->getptr(),
- MED.write_protected, MED.heads, MED.tracks, MED.sectors_per_track));
-#undef MED
- }
- }
-
-
- //
- // Floppy B setup
- //
- BX_FD_THIS s.media[1].sectors_per_track = 0;
- BX_FD_THIS s.media[1].tracks = 0;
- BX_FD_THIS s.media[1].heads = 0;
- BX_FD_THIS s.media[1].sectors = 0;
- BX_FD_THIS s.media[1].fd = -1;
- BX_FD_THIS s.media_present[1] = 0;
- BX_FD_THIS s.device_type[1] = bx_options.floppyb.Odevtype->get ();
-
- switch (BX_FD_THIS s.device_type[1]) {
- case BX_FLOPPY_NONE:
- DEV_cmos_set_reg(0x10, (DEV_cmos_get_reg(0x10) & 0xf0) | 0x00);
- break;
- case BX_FLOPPY_360K:
- DEV_cmos_set_reg(0x10, (DEV_cmos_get_reg(0x10) & 0xf0) | 0x01);
- break;
- case BX_FLOPPY_1_2:
- DEV_cmos_set_reg(0x10, (DEV_cmos_get_reg(0x10) & 0xf0) | 0x02);
- break;
- case BX_FLOPPY_720K:
- DEV_cmos_set_reg(0x10, (DEV_cmos_get_reg(0x10) & 0xf0) | 0x03);
- break;
- case BX_FLOPPY_1_44:
- DEV_cmos_set_reg(0x10, (DEV_cmos_get_reg(0x10) & 0xf0) | 0x04);
- break;
- case BX_FLOPPY_2_88:
- DEV_cmos_set_reg(0x10, (DEV_cmos_get_reg(0x10) & 0xf0) | 0x05);
- break;
-
- // use CMOS reserved types
- case BX_FLOPPY_160K:
- DEV_cmos_set_reg(0x10, (DEV_cmos_get_reg(0x10) & 0xf0) | 0x06);
- BX_INFO(("WARNING: 2nd floppy uses of reserved CMOS floppy drive type 6"));
- break;
- case BX_FLOPPY_180K:
- DEV_cmos_set_reg(0x10, (DEV_cmos_get_reg(0x10) & 0xf0) | 0x07);
- BX_INFO(("WARNING: 2nd floppy uses of reserved CMOS floppy drive type 7"));
- break;
- case BX_FLOPPY_320K:
- DEV_cmos_set_reg(0x10, (DEV_cmos_get_reg(0x10) & 0xf0) | 0x08);
- BX_INFO(("WARNING: 2nd floppy uses of reserved CMOS floppy drive type 8"));
- break;
-
- default:
- BX_PANIC(("unknown floppyb type"));
- }
- if (BX_FD_THIS s.device_type[1] != BX_FLOPPY_NONE)
- BX_FD_THIS s.num_supported_floppies++;
-
- if (bx_options.floppyb.Otype->get () != BX_FLOPPY_NONE) {
- if ( bx_options.floppyb.Ostatus->get () == BX_INSERTED) {
- if (evaluate_media(bx_options.floppyb.Otype->get (), bx_options.floppyb.Opath->getptr (),
- & BX_FD_THIS s.media[1]))
- BX_FD_THIS s.media_present[1] = 1;
- else
- bx_options.floppyb.Ostatus->set(BX_EJECTED);
-#define MED (BX_FD_THIS s.media[1])
- BX_INFO(("fd1: '%s' ro=%d, h=%d,t=%d,spt=%d", bx_options.floppyb.Opath->getptr(),
- MED.write_protected, MED.heads, MED.tracks, MED.sectors_per_track));
-#undef MED
- }
- }
-
-
-
- /* CMOS Equipment Byte register */
- if (BX_FD_THIS s.num_supported_floppies > 0) {
- DEV_cmos_set_reg(0x14, (DEV_cmos_get_reg(0x14) & 0x3e) |
- ((BX_FD_THIS s.num_supported_floppies-1) << 6) | 1);
- }
- else
- DEV_cmos_set_reg(0x14, (DEV_cmos_get_reg(0x14) & 0x3e));
-
-
- if (BX_FD_THIS s.floppy_timer_index == BX_NULL_TIMER_HANDLE) {
- BX_FD_THIS s.floppy_timer_index =
- bx_pc_system.register_timer( this, timer_handler,
- bx_options.Ofloppy_command_delay->get (), 0,0, "floppy");
- }
-
- BX_DEBUG(("bx_options.Ofloppy_command_delay = %u",
- (unsigned) bx_options.Ofloppy_command_delay->get ()));
-}
-
-
-
- void
-bx_floppy_ctrl_c::reset(unsigned type)
-{
- Bit32u i;
-
- BX_FD_THIS s.pending_irq = 0;
- BX_FD_THIS s.reset_sensei = 0; /* no reset result present */
-
- BX_FD_THIS s.main_status_reg = 0;
- BX_FD_THIS s.status_reg0 = 0;
- BX_FD_THIS s.status_reg1 = 0;
- BX_FD_THIS s.status_reg2 = 0;
- BX_FD_THIS s.status_reg3 = 0;
-
- // software reset (via DOR port 0x3f2 bit 2) does not change DOR
- if (type == BX_RESET_HARDWARE) {
- BX_FD_THIS s.DOR = 0x0c;
- // motor off, drive 3..0
- // DMA/INT enabled
- // normal operation
- // drive select 0
-
- // DIR and CCR affected only by hard reset
- for (i=0; i<4; i++) {
- BX_FD_THIS s.DIR[i] |= 0x80; // disk changed
- }
- BX_FD_THIS s.data_rate = 0; /* 500 Kbps */
- }
-
- for (i=0; i<4; i++) {
- BX_FD_THIS s.cylinder[i] = 0;
- BX_FD_THIS s.head[i] = 0;
- BX_FD_THIS s.sector[i] = 0;
- }
-
- DEV_pic_lower_irq(6);
- DEV_dma_set_drq(FLOPPY_DMA_CHAN, 0);
- enter_idle_phase();
-}
-
-
- // static IO port read callback handler
- // redirects to non-static class handler to avoid virtual functions
-
- Bit32u
-bx_floppy_ctrl_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len)
-{
-#if !BX_USE_FD_SMF
- bx_floppy_ctrl_c *class_ptr = (bx_floppy_ctrl_c *) this_ptr;
-
- return( class_ptr->read(address, io_len) );
-}
-
-
- /* reads from the floppy io ports */
- Bit32u
-bx_floppy_ctrl_c::read(Bit32u address, unsigned io_len)
-{
-#else
- UNUSED(this_ptr);
-#endif // !BX_USE_FD_SMF
- Bit8u status, value;
-
- if (bx_dbg.floppy)
- BX_INFO(("read access to port %04x", (unsigned) address));
-
- switch (address) {
-#if BX_DMA_FLOPPY_IO
- case 0x3F2: // diskette controller digital output register
- value = BX_FD_THIS s.DOR;
- return(value);
- break;
-
- case 0x3F4: /* diskette controller main status register */
- status = BX_FD_THIS s.main_status_reg;
- return(status);
- break;
-
- case 0x3F5: /* diskette controller data */
- if (BX_FD_THIS s.result_size == 0) {
- BX_ERROR(("port 0x3f5: no results to read"));
- BX_FD_THIS s.main_status_reg = 0;
- return BX_FD_THIS s.result[0];
- }
-
- value = BX_FD_THIS s.result[BX_FD_THIS s.result_index++];
- BX_FD_THIS s.main_status_reg &= 0xF0;
- if (BX_FD_THIS s.result_index >= BX_FD_THIS s.result_size) {
- if (!BX_FD_THIS s.reset_sensei) BX_FD_THIS s.pending_irq = 0;
- DEV_pic_lower_irq(6);
- enter_idle_phase();
- }
- return(value);
- break;
-#endif // #if BX_DMA_FLOPPY_IO
-
- case 0x3F3: // Tape Drive Register
- // see http://www.smsc.com/main/datasheets/37c93x.pdf page 18 for more details
-
- switch( BX_FD_THIS s.DOR & 0x03 )
- {
- case 0x00:
- if( (BX_FD_THIS s.DOR & 0x10) == 0) break;
- return(2);
- case 0x01:
- if( (BX_FD_THIS s.DOR & 0x20) == 0) break;
- return(1);
- }
- return(3);
-
- case 0x3F6: // Reserved for future floppy controllers
- // This address shared with the hard drive controller
- value = DEV_hd_read_handler(bx_devices.pluginHardDrive, address, io_len);
- return( value );
- break;
-
- case 0x3F7: // diskette controller digital input register
- // This address shared with the hard drive controller:
- // Bit 7 : floppy
- // Bits 6..0: hard drive
- value = DEV_hd_read_handler(bx_devices.pluginHardDrive, address, io_len);
- value &= 0x7f;
- // add in diskette change line
- value |= (BX_FD_THIS s.DIR[BX_FD_THIS s.DOR & 0x03] & 0x80);
- return( value );
- break;
- default:
- BX_ERROR(("io_read: unsupported address 0x%04x", (unsigned) address));
- return(0);
- break;
- }
-}
-
-
- // static IO port write callback handler
- // redirects to non-static class handler to avoid virtual functions
-
- void
-bx_floppy_ctrl_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len)
-{
-#if !BX_USE_FD_SMF
- bx_floppy_ctrl_c *class_ptr = (bx_floppy_ctrl_c *) this_ptr;
-
- class_ptr->write(address, value, io_len);
-}
-
- /* writes to the floppy io ports */
- void
-bx_floppy_ctrl_c::write(Bit32u address, Bit32u value, unsigned io_len)
-{
-#else
- UNUSED(this_ptr);
-#endif // !BX_USE_FD_SMF
- Bit8u dma_and_interrupt_enable;
- Bit8u normal_operation, prev_normal_operation;
- Bit8u drive_select;
- Bit8u motor_on_drive0, motor_on_drive1;
-
- if (bx_dbg.floppy)
- BX_INFO(("write access to port %04x, value=%02x",
- (unsigned) address, (unsigned) value));
-
- switch (address) {
-#if BX_DMA_FLOPPY_IO
- case 0x3F2: /* diskette controller digital output register */
- motor_on_drive1 = value & 0x20;
- motor_on_drive0 = value & 0x10;
- dma_and_interrupt_enable = value & 0x08;
- if (!dma_and_interrupt_enable)
- BX_DEBUG(("DMA and interrupt capabilities disabled"));
- normal_operation = value & 0x04;
- drive_select = value & 0x03;
-
- prev_normal_operation = BX_FD_THIS s.DOR & 0x04;
- BX_FD_THIS s.DOR = value;
-
- if (prev_normal_operation==0 && normal_operation) {
- // transition from RESET to NORMAL
- bx_pc_system.activate_timer( BX_FD_THIS s.floppy_timer_index,
- bx_options.Ofloppy_command_delay->get (), 0 );
- }
- else if (prev_normal_operation && normal_operation==0) {
- // transition from NORMAL to RESET
- BX_FD_THIS s.main_status_reg = FD_MS_BUSY;
- BX_FD_THIS s.pending_command = 0xfe; // RESET pending
-
- }
- BX_DEBUG(("io_write: digital output register"));
- BX_DEBUG((" motor on, drive1 = %d", motor_on_drive1 > 0));
- BX_DEBUG((" motor on, drive0 = %d", motor_on_drive0 > 0));
- BX_DEBUG((" dma_and_interrupt_enable=%02x",
- (unsigned) dma_and_interrupt_enable));
- BX_DEBUG((" normal_operation=%02x",
- (unsigned) normal_operation));
- BX_DEBUG((" drive_select=%02x",
- (unsigned) drive_select));
- if (BX_FD_THIS s.device_type[drive_select] == BX_FLOPPY_NONE) {
- BX_DEBUG(("WARNING: not existing drive selected"));
- }
- break;
-
- case 0x3f4: /* diskette controller data rate select register */
- BX_ERROR(("io_write: data rate select register unsupported"));
- break;
-
- case 0x3F5: /* diskette controller data */
- BX_DEBUG(("command = %02x", (unsigned) value));
- if (BX_FD_THIS s.command_complete) {
- if (BX_FD_THIS s.pending_command!=0)
- BX_PANIC(("io: 3f5: receiving new comm, old one (%02x) pending",
- (unsigned) BX_FD_THIS s.pending_command));
- BX_FD_THIS s.command[0] = value;
- BX_FD_THIS s.command_complete = 0;
- BX_FD_THIS s.command_index = 1;
- /* read/write command in progress */
- BX_FD_THIS s.main_status_reg = FD_MS_MRQ | FD_MS_BUSY;
- switch (value) {
- case 0x03: /* specify */
- BX_FD_THIS s.command_size = 3;
- break;
- case 0x04: // get status
- BX_FD_THIS s.command_size = 2;
- break;
- case 0x07: /* recalibrate */
- BX_FD_THIS s.command_size = 2;
- break;
- case 0x08: /* sense interrupt status */
- BX_FD_THIS s.command_size = 1;
- break;
- case 0x0f: /* seek */
- BX_FD_THIS s.command_size = 3;
- break;
- case 0x4a: /* read ID */
- BX_FD_THIS s.command_size = 2;
- break;
- case 0x4d: /* format track */
- BX_FD_THIS s.command_size = 6;
- break;
- case 0x45:
- case 0xc5: /* write normal data */
- BX_FD_THIS s.command_size = 9;
- break;
- case 0x46:
- case 0x66:
- case 0xc6:
- case 0xe6: /* read normal data */
- BX_FD_THIS s.command_size = 9;
- break;
-
- case 0x13: // Configure command (Enhanced)
- BX_FD_THIS s.command_size = 4;
- break;
-
- case 0x0e: // dump registers (Enhanced drives)
- case 0x10: // Version command, standard controller returns 80h
- case 0x18: // National Semiconductor version command; return 80h
- // These commands are not implemented on the standard
- // controller and return an error. They are available on
- // the enhanced controller.
- BX_DEBUG(("io_write: 0x3f5: unsupported floppy command 0x%02x",
- (unsigned) value));
- BX_FD_THIS s.command_size = 0; // make sure we don't try to process this command
- BX_FD_THIS s.status_reg0 = 0x80; // status: invalid command
- enter_result_phase();
- break;
-
- default:
- BX_ERROR(("io_write: 0x3f5: invalid floppy command 0x%02x",
- (unsigned) value));
- BX_FD_THIS s.command_size = 0; // make sure we don't try to process this command
- BX_FD_THIS s.status_reg0 = 0x80; // status: invalid command
- enter_result_phase();
- break;
- }
- }
- else {
- BX_FD_THIS s.command[BX_FD_THIS s.command_index++] =
- value;
- }
- if (BX_FD_THIS s.command_index ==
- BX_FD_THIS s.command_size) {
- /* read/write command not in progress any more */
- floppy_command();
- BX_FD_THIS s.command_complete = 1;
- }
- BX_DEBUG(("io_write: diskette controller data"));
- return;
- break;
-#endif // #if BX_DMA_FLOPPY_IO
-
- case 0x3F6: /* diskette controller (reserved) */
- BX_DEBUG(("io_write: reserved register 0x3f6 unsupported"));
- // this address shared with the hard drive controller
- DEV_hd_write_handler(bx_devices.pluginHardDrive, address, value, io_len);
- break;
-
-#if BX_DMA_FLOPPY_IO
- case 0x3F7: /* diskette controller configuration control register */
- BX_DEBUG(("io_write: config control register"));
- BX_FD_THIS s.data_rate = value & 0x03;
- switch (BX_FD_THIS s.data_rate) {
- case 0: BX_DEBUG((" 500 Kbps")); break;
- case 1: BX_DEBUG((" 300 Kbps")); break;
- case 2: BX_DEBUG((" 250 Kbps")); break;
- case 3: BX_DEBUG((" 1 Mbps")); break;
- }
- return;
- break;
-
- default:
- BX_ERROR(("io_write ignored: 0x%04x = 0x%02x", (unsigned) address, (unsigned) value));
- break;
-#endif // #if BX_DMA_FLOPPY_IO
- }
-}
-
-
-
- void
-bx_floppy_ctrl_c::floppy_command(void)
-{
-#if BX_PROVIDE_CPU_MEMORY==0
- BX_PANIC(("floppy_command(): uses DMA: not supported for"
- " external environment"));
-#else
- unsigned i;
- Bit8u step_rate_time;
- Bit8u head_unload_time;
- Bit8u head_load_time;
- Bit8u motor_on;
- Bit8u head, drive, cylinder, sector, eot;
- Bit8u sector_size, data_length;
- Bit32u logical_sector;
-
-
- BX_DEBUG(("FLOPPY COMMAND: "));
- for (i=0; i<BX_FD_THIS s.command_size; i++)
- BX_DEBUG(("[%02x] ", (unsigned) BX_FD_THIS s.command[i]));
-
-#if 0
- /* execute phase of command is in progress (non DMA mode) */
- BX_FD_THIS s.main_status_reg |= 20;
-#endif
-
- BX_FD_THIS s.pending_command = BX_FD_THIS s.command[0];
- switch (BX_FD_THIS s.pending_command) {
- case 0x03: // specify
- // execution: specified parameters are loaded
- // result: no result bytes, no interrupt
- step_rate_time = BX_FD_THIS s.command[1] >> 4;
- head_unload_time = BX_FD_THIS s.command[1] & 0x0f;
- head_load_time = BX_FD_THIS s.command[2] >> 1;
- if (BX_FD_THIS s.command[2] & 0x01)
- BX_ERROR(("non DMA mode selected"));
- enter_idle_phase();
- return;
- break;
-
- case 0x04: // get status
- drive = (BX_FD_THIS s.command[1] & 0x03);
- BX_FD_THIS s.head[drive] = (BX_FD_THIS s.command[1] >> 2) & 0x01;
- BX_FD_THIS s.status_reg3 = 0x28 | (BX_FD_THIS s.head[drive]<<2) | drive
- | (BX_FD_THIS s.media[drive].write_protected ? 0x40 : 0x00);
- if (BX_FD_THIS s.cylinder[drive] == 0) BX_FD_THIS s.status_reg3 |= 0x10;
- enter_result_phase();
- return;
- break;
-
- case 0x07: // recalibrate
- drive = (BX_FD_THIS s.command[1] & 0x03);
- BX_FD_THIS s.DOR &= 0xfc;
- BX_FD_THIS s.DOR |= drive;
- BX_DEBUG(("floppy_command(): recalibrate drive %u",
- (unsigned) drive));
- motor_on = ( (BX_FD_THIS s.DOR>>(drive+4))
- & 0x01 );
- if (motor_on == 0) {
- BX_INFO(("floppy_command(): recal drive with motor off"));
- }
- if (drive==0)
- BX_FD_THIS s.DOR |= 0x10; // turn on MOTA
- else
- BX_FD_THIS s.DOR |= 0x20; // turn on MOTB
- bx_pc_system.activate_timer( BX_FD_THIS s.floppy_timer_index,
- bx_options.Ofloppy_command_delay->get (), 0 );
- /* command head to track 0
- * controller set to non-busy
- * error condition noted in Status reg 0's equipment check bit
- * seek end bit set to 1 in Status reg 0 regardless of outcome
- * The last two are taken care of in timer().
- */
- BX_FD_THIS s.cylinder[drive] = 0;
- BX_FD_THIS s.main_status_reg = (1 << drive);
- return;
- break;
-
- case 0x08: /* sense interrupt status */
- /* execution:
- * get status
- * result:
- * no interupt
- * byte0 = status reg0
- * byte1 = current cylinder number (0 to 79)
- */
- drive = BX_FD_THIS s.DOR & 0x03;
- if (!BX_FD_THIS s.pending_irq) {
- BX_FD_THIS s.status_reg0 = 0x80;
- }
- else {
- if (BX_FD_THIS s.reset_sensei > 0) {
- drive = 4 - BX_FD_THIS s.reset_sensei;
- BX_FD_THIS s.status_reg0 &= 0xf8;
- BX_FD_THIS s.status_reg0 |= (BX_FD_THIS s.head[drive] << 2) | drive;
- BX_FD_THIS s.reset_sensei--;
- }
- }
-
- BX_DEBUG(("sense interrupt status"));
- enter_result_phase();
- return;
- break;
-
- case 0x0f: /* seek */
- /* command:
- * byte0 = 0F
- * byte1 = drive & head select
- * byte2 = cylinder number
- * execution:
- * postion head over specified cylinder
- * result:
- * no result bytes, issues an interrupt
- */
- drive = BX_FD_THIS s.command[1] & 0x03;
- BX_FD_THIS s.DOR &= 0xfc;
- BX_FD_THIS s.DOR |= drive;
-
- BX_FD_THIS s.head[drive] = (BX_FD_THIS s.command[1] >> 2) & 0x01;
- BX_FD_THIS s.cylinder[drive] = BX_FD_THIS s.command[2];
- /* ??? should also check cylinder validity */
- bx_pc_system.activate_timer( BX_FD_THIS s.floppy_timer_index,
- bx_options.Ofloppy_command_delay->get (), 0 );
- /* data reg not ready, drive busy */
- BX_FD_THIS s.main_status_reg = (1 << drive);
- return;
- break;
-
- case 0x13: // Configure
- BX_DEBUG(("configure (eis = 0x%02x)", BX_FD_THIS s.command[2] & 0x40 ));
- BX_DEBUG(("configure (efifo = 0x%02x)", BX_FD_THIS s.command[2] & 0x20 ));
- BX_DEBUG(("configure (no poll = 0x%02x)", BX_FD_THIS s.command[2] & 0x10 ));
- BX_DEBUG(("configure (fifothr = 0x%02x)", BX_FD_THIS s.command[2] & 0x0f ));
- BX_DEBUG(("configure (pretrk = 0x%02x)", BX_FD_THIS s.command[3] ));
- enter_idle_phase();
- return;
- break;
-
- case 0x4a: // read ID
- drive = BX_FD_THIS s.command[1] & 0x03;
- BX_FD_THIS s.head[drive] = (BX_FD_THIS s.command[1] >> 2) & 0x01;
- BX_FD_THIS s.DOR &= 0xfc;
- BX_FD_THIS s.DOR |= drive;
-
- motor_on = (BX_FD_THIS s.DOR>>(drive+4)) & 0x01;
- if (motor_on == 0) {
- BX_ERROR(("floppy_command(): 0x4a: motor not on"));
- BX_FD_THIS s.main_status_reg = FD_MS_BUSY;
- return;
- }
- if (BX_FD_THIS s.device_type[drive] == BX_FLOPPY_NONE)
- BX_PANIC(("floppy_command(): read ID: bad drive #%d", drive));
- BX_FD_THIS s.status_reg0 = (BX_FD_THIS s.head[drive]<<2) | drive;
- bx_pc_system.activate_timer( BX_FD_THIS s.floppy_timer_index,
- bx_options.Ofloppy_command_delay->get (), 0 );
- /* data reg not ready, controller busy */
- BX_FD_THIS s.main_status_reg = FD_MS_BUSY;
- return;
- break;
-
- case 0x4d: // format track
- drive = BX_FD_THIS s.command[1] & 0x03;
- BX_FD_THIS s.DOR &= 0xfc;
- BX_FD_THIS s.DOR |= drive;
-
- motor_on = (BX_FD_THIS s.DOR>>(drive+4)) & 0x01;
- if (motor_on == 0)
- BX_PANIC(("floppy_command(): format track: motor not on"));
- BX_FD_THIS s.head[drive] = (BX_FD_THIS s.command[1] >> 2) & 0x01;
- sector_size = BX_FD_THIS s.command[2];
- BX_FD_THIS s.format_count = BX_FD_THIS s.command[3];
- BX_FD_THIS s.format_fillbyte = BX_FD_THIS s.command[5];
- if (BX_FD_THIS s.device_type[drive] == BX_FLOPPY_NONE)
- BX_PANIC(("floppy_command(): format track: bad drive #%d", drive));
-
- if (sector_size != 0x02) { // 512 bytes
- BX_PANIC(("format track: sector size %d not supported", 128<<sector_size));
- }
- if (BX_FD_THIS s.format_count != BX_FD_THIS s.media[drive].sectors_per_track) {
- BX_PANIC(("format track: %d sectors/track requested (%d expected)",
- BX_FD_THIS s.format_count, BX_FD_THIS s.media[drive].sectors_per_track));
- }
- if ( BX_FD_THIS s.media_present[drive] == 0 ) {
- // media not in drive, return error
- BX_INFO(("attempt to format track with media not present"));
- BX_FD_THIS s.status_reg0 = 0x40 | (BX_FD_THIS s.head[drive]<<2) | drive; // abnormal termination
- BX_FD_THIS s.status_reg1 = 0x25; // 0010 0101
- BX_FD_THIS s.status_reg2 = 0x31; // 0011 0001
- enter_result_phase();
- return;
- }
- if (BX_FD_THIS s.media[drive].write_protected) {
- // media write-protected, return error
- BX_INFO(("attempt to format track with media write-protected"));
- BX_FD_THIS s.status_reg0 = 0x40 | (BX_FD_THIS s.head[drive]<<2) | drive; // abnormal termination
- BX_FD_THIS s.status_reg1 = 0x27; // 0010 0111
- BX_FD_THIS s.status_reg2 = 0x31; // 0011 0001
- enter_result_phase();
- return;
- }
-
- /* 4 header bytes per sector are required */
- BX_FD_THIS s.format_count <<= 2;
-
- DEV_dma_set_drq(FLOPPY_DMA_CHAN, 1);
-
- /* data reg not ready, controller busy */
- BX_FD_THIS s.main_status_reg = FD_MS_BUSY;
- BX_DEBUG(("format track"));
- return;
- break;
-
- case 0x46: // read normal data, MT=0, SK=0
- case 0x66: // read normal data, MT=0, SK=1
- case 0xc6: // read normal data, MT=1, SK=0
- case 0xe6: // read normal data, MT=1, SK=1
- case 0x45: // write normal data, MT=0
- case 0xc5: // write normal data, MT=1
- BX_FD_THIS s.multi_track = (BX_FD_THIS s.command[0] >> 7);
- if ( (BX_FD_THIS s.DOR & 0x08) == 0 )
- BX_PANIC(("read/write command with DMA and int disabled"));
- drive = BX_FD_THIS s.command[1] & 0x03;
- BX_FD_THIS s.DOR &= 0xfc;
- BX_FD_THIS s.DOR |= drive;
-
- motor_on = (BX_FD_THIS s.DOR>>(drive+4)) & 0x01;
- if (motor_on == 0)
- BX_PANIC(("floppy_command(): read/write: motor not on"));
- head = BX_FD_THIS s.command[3] & 0x01;
- cylinder = BX_FD_THIS s.command[2]; /* 0..79 depending */
- sector = BX_FD_THIS s.command[4]; /* 1..36 depending */
- eot = BX_FD_THIS s.command[6]; /* 1..36 depending */
- sector_size = BX_FD_THIS s.command[5];
- data_length = BX_FD_THIS s.command[8];
- BX_DEBUG(("read/write normal data"));
- BX_DEBUG(("BEFORE"));
- BX_DEBUG((" drive = %u", (unsigned) drive));
- BX_DEBUG((" head = %u", (unsigned) head));
- BX_DEBUG((" cylinder = %u", (unsigned) cylinder));
- BX_DEBUG((" sector = %u", (unsigned) sector));
- BX_DEBUG((" eot = %u", (unsigned) eot));
- if (BX_FD_THIS s.device_type[drive] == BX_FLOPPY_NONE)
- BX_PANIC(("floppy_command(): read/write: bad drive #%d", drive));
-
- // check that head number in command[1] bit two matches the head
- // reported in the head number field. Real floppy drives are
- // picky about this, as reported in SF bug #439945, (Floppy drive
- // read input error checking).
- if (head != ((BX_FD_THIS s.command[1]>>2)&1)) {
- BX_ERROR(("head number in command[1] doesn't match head field"));
- BX_FD_THIS s.status_reg0 = 0x40 | (BX_FD_THIS s.head[drive]<<2) | drive; // abnormal termination
- BX_FD_THIS s.status_reg1 = 0x04; // 0000 0100
- BX_FD_THIS s.status_reg2 = 0x00; // 0000 0000
- enter_result_phase();
- return;
- }
-
- if ( BX_FD_THIS s.media_present[drive] == 0 ) {
- // media not in drive, return error
-
- BX_INFO(("attempt to read/write sector %u,"
- " sectors/track=%u with media not present",
- (unsigned) sector,
- (unsigned) BX_FD_THIS s.media[drive].sectors_per_track));
- BX_FD_THIS s.status_reg0 = 0x40 | (BX_FD_THIS s.head[drive]<<2) | drive; // abnormal termination
- BX_FD_THIS s.status_reg1 = 0x25; // 0010 0101
- BX_FD_THIS s.status_reg2 = 0x31; // 0011 0001
- enter_result_phase();
- return;
- }
-
- if (sector_size != 0x02) { // 512 bytes
- BX_PANIC(("read/write command: sector size %d not supported", 128<<sector_size));
- }
- if ( cylinder >= BX_FD_THIS s.media[drive].tracks ) {
- BX_PANIC(("io: norm r/w parms out of range: sec#%02xh cyl#%02xh eot#%02xh head#%02xh",
- (unsigned) sector, (unsigned) cylinder, (unsigned) eot,
- (unsigned) head));
- return;
- }
-
- if (sector > BX_FD_THIS s.media[drive].sectors_per_track) {
- // requested sector > last sector on track
- BX_INFO(("attempt to read/write sector %u,"
- " sectors/track=%u", (unsigned) sector,
- (unsigned) BX_FD_THIS s.media[drive].sectors_per_track));
- // set controller to where drive would have left off
- // after it discovered the sector was past EOT
- BX_FD_THIS s.cylinder[drive] = cylinder;
- BX_FD_THIS s.head[drive] = head;
- BX_FD_THIS s.sector[drive] = BX_FD_THIS s.media[drive].sectors_per_track;
-
- // 0100 0HDD abnormal termination
- BX_FD_THIS s.status_reg0 = 0x40 | (BX_FD_THIS s.head[drive]<<2) | drive;
- // 1000 0101 end of cyl/NDAT/NID
- BX_FD_THIS s.status_reg1 = 0x85;
- // 0000 0000
- BX_FD_THIS s.status_reg2 = 0x00;
- enter_result_phase();
- return;
- }
-
- if (cylinder != BX_FD_THIS s.cylinder[drive])
- BX_DEBUG(("io: cylinder request != current cylinder"));
-
- // original assumed all floppies had two sides...now it does not *delete this comment line*
- logical_sector = (cylinder * BX_FD_THIS s.media[drive].heads * BX_FD_THIS s.media[drive].sectors_per_track) +
- (head * BX_FD_THIS s.media[drive].sectors_per_track) +
- (sector - 1);
-
- if (logical_sector >= BX_FD_THIS s.media[drive].sectors) {
- BX_PANIC(("io: logical sector out of bounds"));
- }
-
- BX_FD_THIS s.cylinder[drive] = cylinder;
- BX_FD_THIS s.sector[drive] = sector;
- BX_FD_THIS s.head[drive] = head;
-
- if ((BX_FD_THIS s.command[0] & 0x4f) == 0x46) { // read
- floppy_xfer(drive, logical_sector*512, BX_FD_THIS s.floppy_buffer,
- 512, FROM_FLOPPY);
-
- DEV_dma_set_drq(FLOPPY_DMA_CHAN, 1);
-
- /* data reg not ready, controller busy */
- BX_FD_THIS s.main_status_reg = FD_MS_BUSY;
- return;
- }
- else if ((BX_FD_THIS s.command[0] & 0x7f) == 0x45) { // write
-
- DEV_dma_set_drq(FLOPPY_DMA_CHAN, 1);
-
- /* data reg not ready, controller busy */
- BX_FD_THIS s.main_status_reg = FD_MS_BUSY;
- return;
- }
- else
- BX_PANIC(("floppy_command(): unknown read/write command"));
-
- return;
- break;
-
- default: // invalid or unsupported command; these are captured in write() above
- BX_PANIC(("You should never get here! cmd = 0x%02x",
- BX_FD_THIS s.command[0]));
- }
-#endif
-}
-
- void
-bx_floppy_ctrl_c::floppy_xfer(Bit8u drive, Bit32u offset, Bit8u *buffer,
- Bit32u bytes, Bit8u direction)
-{
- int ret;
-
- if (BX_FD_THIS s.device_type[drive] == BX_FLOPPY_NONE)
- BX_PANIC(("floppy_xfer: bad drive #%d", drive));
-
- if (bx_dbg.floppy) {
- BX_INFO(("drive=%u", (unsigned) drive));
- BX_INFO(("offset=%u", (unsigned) offset));
- BX_INFO(("bytes=%u", (unsigned) bytes));
- BX_INFO(("direction=%s", (direction==FROM_FLOPPY)? "from" : "to"));
- }
-
-#if BX_WITH_MACOS
- if (strcmp(bx_options.floppya.Opath->getptr (), SuperDrive))
-#endif
- {
- ret = lseek(BX_FD_THIS s.media[drive].fd, offset, SEEK_SET);
- if (ret < 0) {
- BX_PANIC(("could not perform lseek() on floppy image file"));
- }
- }
-
- if (direction == FROM_FLOPPY) {
-#if BX_WITH_MACOS
- if (!strcmp(bx_options.floppya.Opath->getptr (), SuperDrive))
- ret = fd_read((char *) buffer, offset, bytes);
- else
-#endif
- ret = ::read(BX_FD_THIS s.media[drive].fd, (bx_ptr_t) buffer, bytes);
- if (ret < int(bytes)) {
- /* ??? */
- if (ret > 0) {
- BX_INFO(("partial read() on floppy image returns %u/%u",
- (unsigned) ret, (unsigned) bytes));
- memset(buffer + ret, 0, bytes - ret);
- }
- else {
- BX_INFO(("read() on floppy image returns 0"));
- memset(buffer, 0, bytes);
- }
- }
- }
-
- else { // TO_FLOPPY
- BX_ASSERT (!BX_FD_THIS s.media[drive].write_protected);
-#if BX_WITH_MACOS
- if (!strcmp(bx_options.floppya.Opath->getptr (), SuperDrive))
- ret = fd_write((char *) buffer, offset, bytes);
- else
-#endif
- ret = ::write(BX_FD_THIS s.media[drive].fd, (bx_ptr_t) buffer, bytes);
- if (ret < int(bytes)) {
- BX_PANIC(("could not perform write() on floppy image file"));
- }
- }
-}
-
-
-
- void
-bx_floppy_ctrl_c::timer_handler(void *this_ptr)
-{
-
- bx_floppy_ctrl_c *class_ptr = (bx_floppy_ctrl_c *) this_ptr;
-
- class_ptr->timer();
-}
-
- void
-bx_floppy_ctrl_c::timer()
-{
- Bit8u drive;
-
- drive = BX_FD_THIS s.DOR & 0x03;
- switch ( BX_FD_THIS s.pending_command ) {
- case 0x07: // recal
- case 0x0f: // seek
- BX_FD_THIS s.status_reg0 = 0x20 | (BX_FD_THIS s.head[drive]<<2) | drive;
- if (BX_FD_THIS s.device_type[drive] == BX_FLOPPY_NONE) {
- BX_FD_THIS s.status_reg0 |= 0x50;
- }
- else if (BX_FD_THIS s.media_present[drive] == 0) {
- BX_FD_THIS s.status_reg0 |= 0x40;
- BX_FD_THIS s.status_reg1 = 0x25;
- BX_FD_THIS s.status_reg2 = 0x31;
- }
-
- /* reset changeline */
- if (drive > 1) return;
- if (BX_FD_THIS s.media_present[drive])
- BX_FD_THIS s.DIR[drive] &= ~0x80; // clear disk change line
-
- enter_idle_phase();
- raise_interrupt();
- break;
-
- case 0x4a: /* read ID */
- enter_result_phase();
- break;
-
- case 0xfe: // (contrived) RESET
- theFloppyController->reset(BX_RESET_SOFTWARE);
- BX_FD_THIS s.pending_command = 0;
- BX_FD_THIS s.status_reg0 = 0xc0;
- raise_interrupt();
- BX_FD_THIS s.reset_sensei = 4;
- break;
-
- case 0x00: // nothing pending?
- break;
-
- default:
- BX_PANIC(("floppy:timer(): unknown case %02x",
- (unsigned) BX_FD_THIS s.pending_command));
- }
- return;
-}
-
- void
-bx_floppy_ctrl_c::dma_write(Bit8u *data_byte)
-{
- // A DMA write is from I/O to Memory
- // We need to return then next data byte from the floppy buffer
- // to be transfered via the DMA to memory. (read block from floppy)
-
-
- *data_byte = BX_FD_THIS s.floppy_buffer[BX_FD_THIS s.floppy_buffer_index++];
-
- if (BX_FD_THIS s.floppy_buffer_index >= 512) {
- Bit8u drive;
-
- drive = BX_FD_THIS s.DOR & 0x03;
- increment_sector(); // increment to next sector before retrieving next one
- BX_FD_THIS s.floppy_buffer_index = 0;
- if (DEV_dma_get_tc()) { // Terminal Count line, done
- BX_FD_THIS s.status_reg0 = (BX_FD_THIS s.head[drive] << 2) | drive;
- BX_FD_THIS s.status_reg1 = 0;
- BX_FD_THIS s.status_reg2 = 0;
-
- if (bx_dbg.floppy) {
- BX_INFO(("<<READ DONE>>"));
- BX_INFO(("AFTER"));
- BX_INFO((" drive = %u", (unsigned) drive));
- BX_INFO((" head = %u", (unsigned) BX_FD_THIS s.head[drive]));
- BX_INFO((" cylinder = %u", (unsigned) BX_FD_THIS s.cylinder[drive]));
- BX_INFO((" sector = %u", (unsigned) BX_FD_THIS s.sector[drive]));
- }
-
- DEV_dma_set_drq(FLOPPY_DMA_CHAN, 0);
- enter_result_phase();
- }
- else { // more data to transfer
- Bit32u logical_sector;
-
- // original assumed all floppies had two sides...now it does not *delete this comment line*
- logical_sector = (BX_FD_THIS s.cylinder[drive] * BX_FD_THIS s.media[drive].heads *
- BX_FD_THIS s.media[drive].sectors_per_track) +
- (BX_FD_THIS s.head[drive] *
- BX_FD_THIS s.media[drive].sectors_per_track) +
- (BX_FD_THIS s.sector[drive] - 1);
-
- floppy_xfer(drive, logical_sector*512, BX_FD_THIS s.floppy_buffer,
- 512, FROM_FLOPPY);
- }
- }
-}
-
- void
-bx_floppy_ctrl_c::dma_read(Bit8u *data_byte)
-{
- // A DMA read is from Memory to I/O
- // We need to write the data_byte which was already transfered from memory
- // via DMA to I/O (write block to floppy)
-
- Bit8u drive;
- Bit32u logical_sector;
-
- drive = BX_FD_THIS s.DOR & 0x03;
- if (BX_FD_THIS s.pending_command == 0x4d) { // format track in progress
- --BX_FD_THIS s.format_count;
- switch (3 - (BX_FD_THIS s.format_count & 0x03)) {
- case 0:
- BX_FD_THIS s.cylinder[drive] = *data_byte;
- break;
- case 1:
- if (*data_byte != BX_FD_THIS s.head[drive])
- BX_ERROR(("head number does not match head field"));
- break;
- case 2:
- BX_FD_THIS s.sector[drive] = *data_byte;
- break;
- case 3:
- if (*data_byte != 2) BX_ERROR(("dma_read: sector size %d not supported", 128<<(*data_byte)));
- BX_DEBUG(("formatting cylinder %u head %u sector %u",
- BX_FD_THIS s.cylinder[drive], BX_FD_THIS s.head[drive],
- BX_FD_THIS s.sector[drive]));
- for (unsigned i = 0; i < 512; i++) {
- BX_FD_THIS s.floppy_buffer[i] = BX_FD_THIS s.format_fillbyte;
- }
- // original assumed all floppies had two sides...now it does not *delete this comment line*
- logical_sector = (BX_FD_THIS s.cylinder[drive] * BX_FD_THIS s.media[drive].heads * BX_FD_THIS s.media[drive].sectors_per_track) +
- (BX_FD_THIS s.head[drive] * BX_FD_THIS s.media[drive].sectors_per_track) +
- (BX_FD_THIS s.sector[drive] - 1);
- floppy_xfer(drive, logical_sector*512, BX_FD_THIS s.floppy_buffer,
- 512, TO_FLOPPY);
- break;
- }
- if ((BX_FD_THIS s.format_count == 0) || (DEV_dma_get_tc())) {
- BX_FD_THIS s.format_count = 0;
- BX_FD_THIS s.status_reg0 = (BX_FD_THIS s.head[drive] << 2) | drive;
- DEV_dma_set_drq(FLOPPY_DMA_CHAN, 0);
- enter_result_phase();
- }
- return;
- }
-
- BX_FD_THIS s.floppy_buffer[BX_FD_THIS s.floppy_buffer_index++] = *data_byte;
-
- if (BX_FD_THIS s.floppy_buffer_index >= 512) {
- // original assumed all floppies had two sides...now it does not *delete this comment line*
- logical_sector = (BX_FD_THIS s.cylinder[drive] * BX_FD_THIS s.media[drive].heads * BX_FD_THIS s.media[drive].sectors_per_track) +
- (BX_FD_THIS s.head[drive] * BX_FD_THIS s.media[drive].sectors_per_track) +
- (BX_FD_THIS s.sector[drive] - 1);
- if ( BX_FD_THIS s.media[drive].write_protected ) {
- // write protected error
- BX_INFO(("tried to write disk %u, which is write-protected", drive));
- // ST0: IC1,0=01 (abnormal termination: started execution but failed)
- BX_FD_THIS s.status_reg0 = 0x40 | (BX_FD_THIS s.head[drive]<<2) | drive;
- // ST1: DataError=1, NDAT=1, NotWritable=1, NID=1
- BX_FD_THIS s.status_reg1 = 0x27; // 0010 0111
- // ST2: CRCE=1, SERR=1, BCYL=1, NDAM=1.
- BX_FD_THIS s.status_reg2 = 0x31; // 0011 0001
- enter_result_phase();
- return;
- }
- floppy_xfer(drive, logical_sector*512, BX_FD_THIS s.floppy_buffer,
- 512, TO_FLOPPY);
- increment_sector(); // increment to next sector after writing current one
- BX_FD_THIS s.floppy_buffer_index = 0;
- if (DEV_dma_get_tc()) { // Terminal Count line, done
- BX_FD_THIS s.status_reg0 = (BX_FD_THIS s.head[drive] << 2) | drive;
- BX_FD_THIS s.status_reg1 = 0;
- BX_FD_THIS s.status_reg2 = 0;
-
- if (bx_dbg.floppy) {
- BX_INFO(("<<WRITE DONE>>"));
- BX_INFO(("AFTER"));
- BX_INFO((" drive = %u", (unsigned) drive));
- BX_INFO((" head = %u", (unsigned) BX_FD_THIS s.head[drive]));
- BX_INFO((" cylinder = %u", (unsigned) BX_FD_THIS s.cylinder[drive]));
- BX_INFO((" sector = %u", (unsigned) BX_FD_THIS s.sector[drive]));
- }
-
- DEV_dma_set_drq(FLOPPY_DMA_CHAN, 0);
- enter_result_phase();
- }
- else { // more data to transfer
- } // else
- } // if BX_FD_THIS s.floppy_buffer_index >= 512
-}
-
- void
-bx_floppy_ctrl_c::raise_interrupt(void)
-{
- DEV_pic_raise_irq(6);
- BX_FD_THIS s.pending_irq = 1;
- BX_FD_THIS s.reset_sensei = 0;
-}
-
-
- void
-bx_floppy_ctrl_c::increment_sector(void)
-{
- Bit8u drive;
-
- drive = BX_FD_THIS s.DOR & 0x03;
-
- // values after completion of data xfer
- // ??? calculation depends on base_count being multiple of 512
- BX_FD_THIS s.sector[drive] ++;
- if (BX_FD_THIS s.sector[drive] > BX_FD_THIS s.media[drive].sectors_per_track) {
- BX_FD_THIS s.sector[drive] = 1;
- if (BX_FD_THIS s.multi_track) {
- BX_FD_THIS s.head[drive] ++;
- if (BX_FD_THIS s.head[drive] > 1) {
- BX_FD_THIS s.head[drive] = 0;
- BX_FD_THIS s.cylinder[drive] ++;
- }
- }
- else {
- BX_FD_THIS s.cylinder[drive] ++;
- }
- if (BX_FD_THIS s.cylinder[drive] >= BX_FD_THIS s.media[drive].tracks) {
- // Set to 1 past last possible cylinder value.
- // I notice if I set it to tracks-1, prama linux won't boot.
- BX_FD_THIS s.cylinder[drive] = BX_FD_THIS s.media[drive].tracks;
- BX_INFO(("increment_sector: clamping cylinder to max"));
- }
- }
-}
-
- unsigned
-bx_floppy_ctrl_c::set_media_status(unsigned drive, unsigned status)
-{
- char *path;
- unsigned type;
-
- if (drive == 0)
- type = bx_options.floppya.Otype->get ();
- else
- type = bx_options.floppyb.Otype->get ();
-
- // if setting to the current value, nothing to do
- if ((status == BX_FD_THIS s.media_present[drive]) &&
- ((status == 0) || (type == BX_FD_THIS s.media[drive].type)))
- return(status);
-
- if (status == 0) {
- // eject floppy
- if (BX_FD_THIS s.media[drive].fd >= 0) {
- close( BX_FD_THIS s.media[drive].fd );
- BX_FD_THIS s.media[drive].fd = -1;
- }
- BX_FD_THIS s.media_present[drive] = 0;
- if (drive == 0) {
- bx_options.floppya.Ostatus->set(BX_EJECTED);
- } else {
- bx_options.floppyb.Ostatus->set(BX_EJECTED);
- }
- BX_FD_THIS s.DIR[drive] |= 0x80; // disk changed line
- return(0);
- }
- else {
- // insert floppy
- if (drive == 0) {
- path = bx_options.floppya.Opath->getptr ();
- }
- else {
- path = bx_options.floppyb.Opath->getptr ();
- }
- if (!strcmp(path, "none"))
- return(0);
- if (evaluate_media(type, path, & BX_FD_THIS s.media[drive])) {
- BX_FD_THIS s.media_present[drive] = 1;
- if (drive == 0) {
-#define MED (BX_FD_THIS s.media[0])
- BX_INFO(("fd0: '%s' ro=%d, h=%d,t=%d,spt=%d", bx_options.floppya.Opath->getptr(),
- MED.write_protected, MED.heads, MED.tracks, MED.sectors_per_track));
-#undef MED
- bx_options.floppya.Ostatus->set(BX_INSERTED);
- } else {
-#define MED (BX_FD_THIS s.media[1])
- BX_INFO(("fd1: '%s' ro=%d, h=%d,t=%d,spt=%d", bx_options.floppyb.Opath->getptr(),
- MED.write_protected, MED.heads, MED.tracks, MED.sectors_per_track));
-#undef MED
- bx_options.floppyb.Ostatus->set(BX_INSERTED);
- }
- BX_FD_THIS s.DIR[drive] |= 0x80; // disk changed line
- return(1);
- }
- else {
- BX_FD_THIS s.media_present[drive] = 0;
- if (drive == 0) {
- bx_options.floppya.Ostatus->set(BX_EJECTED);
- } else {
- bx_options.floppyb.Ostatus->set(BX_EJECTED);
- }
- return(0);
- }
- }
-}
-
- unsigned
-bx_floppy_ctrl_c::get_media_status(unsigned drive)
-{
- return( BX_FD_THIS s.media_present[drive] );
-}
-
-#ifdef O_BINARY
-#define BX_RDONLY O_RDONLY | O_BINARY
-#define BX_RDWR O_RDWR | O_BINARY
-#else
-#define BX_RDONLY O_RDONLY
-#define BX_RDWR O_RDWR
-#endif
-
- bx_bool
-bx_floppy_ctrl_c::evaluate_media(unsigned type, char *path, floppy_t *media)
-{
- struct stat stat_buf;
- int i, ret;
- int idx = -1;
-#ifdef __linux__
- struct floppy_struct floppy_geom;
-#endif
-#ifdef WIN32
- char sTemp[1024];
- bx_bool raw_floppy = 0;
- HANDLE hFile;
- DWORD bytes;
- DISK_GEOMETRY dg;
- unsigned tracks, heads, spt;
-#endif
-
- if (type == BX_FLOPPY_NONE)
- return(0);
-
- //If media file is already open, close it before reopening.
- if(media->fd >=0) {
- close(media->fd);
- media->fd=-1;
- }
-
- // open media file (image file or device)
- media->write_protected = 0;
-#ifdef macintosh
- media->fd = 0;
- if (strcmp(bx_options.floppya.Opath->getptr (), SuperDrive))
-#endif
-#ifdef WIN32
- if ( (isalpha(path[0])) && (path[1] == ':') && (strlen(path) == 2) ) {
- raw_floppy = 1;
- wsprintf(sTemp, "\\\\.\\%s", path);
- hFile = CreateFile(sTemp, GENERIC_READ, FILE_SHARE_WRITE, NULL,
- OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- if (hFile == INVALID_HANDLE_VALUE) {
- BX_ERROR(("Cannot open floppy drive"));
- return(0);
- } else {
- if (!DeviceIoControl(hFile, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &dg, sizeof(dg), &bytes, NULL)) {
- BX_ERROR(("No media in floppy drive"));
- CloseHandle(hFile);
- return(0);
- } else {
- tracks = (unsigned)dg.Cylinders.QuadPart;
- heads = (unsigned)dg.TracksPerCylinder;
- spt = (unsigned)dg.SectorsPerTrack;
- }
- CloseHandle(hFile);
- }
- media->fd = open(sTemp, BX_RDWR);
- } else {
- media->fd = open(path, BX_RDWR);
- }
-#else
- media->fd = open(path, BX_RDWR);
-#endif
-
- if (media->fd < 0) {
- BX_INFO(( "tried to open '%s' read/write: %s",path,strerror(errno) ));
- // try opening the file read-only
- media->write_protected = 1;
-#ifdef macintosh
- media->fd = 0;
- if (strcmp(bx_options.floppya.Opath->getptr (), SuperDrive))
-#endif
-#ifdef WIN32
- if (raw_floppy == 1) {
- media->fd = open(sTemp, BX_RDONLY);
- } else {
- media->fd = open(path, BX_RDONLY);
- }
-#else
- media->fd = open(path, BX_RDONLY);
-#endif
- if (media->fd < 0) {
- // failed to open read-only too
- BX_INFO(( "tried to open '%s' read only: %s",path,strerror(errno) ));
- media->type = type;
- return(0);
- }
- }
-
-#if BX_WITH_MACOS
- if (!strcmp(bx_options.floppya.Opath->getptr (), SuperDrive))
- ret = fd_stat(&stat_buf);
- else
- ret = fstat(media->fd, &stat_buf);
-#elif defined(WIN32)
- if (raw_floppy) {
- memset (&stat_buf, 0, sizeof(stat_buf));
- stat_buf.st_mode = S_IFCHR;
- ret = 0;
- } else {
- ret = fstat(media->fd, &stat_buf);
- }
-#else
- // unix
- ret = fstat(media->fd, &stat_buf);
-#endif
- if (ret) {
- BX_PANIC(("fstat floppy 0 drive image file returns error: %s", strerror(errno)));
- return(0);
- }
-
- for (i = 0; i < 8; i++) {
- if (type == floppy_type[i].id) idx = i;
- }
- if (idx == -1 ) {
- BX_PANIC(("evaluate_media: unknown media type"));
- return(0);
- }
- if ( S_ISREG(stat_buf.st_mode) ) {
- // regular file
- switch (type) {
- // use CMOS reserved types
- case BX_FLOPPY_160K: // 160K 5.25"
- case BX_FLOPPY_180K: // 180K 5.25"
- case BX_FLOPPY_320K: // 320K 5.25"
- // standard floppy types
- case BX_FLOPPY_360K: // 360K 5.25"
- case BX_FLOPPY_720K: // 720K 3.5"
- case BX_FLOPPY_1_2: // 1.2M 5.25"
- case BX_FLOPPY_2_88: // 2.88M 3.5"
- media->type = type;
- media->tracks = floppy_type[idx].trk;
- media->heads = floppy_type[idx].hd;
- media->sectors_per_track = floppy_type[idx].spt;
- media->sectors = floppy_type[idx].sectors;
- if (stat_buf.st_size > (media->sectors * 512)) {
- BX_INFO(("evaluate_media: size of file '%s' (%lu) too large for selected type",
- path, (unsigned long) stat_buf.st_size));
- return(0);
- }
- break;
- default: // 1.44M 3.5"
- media->type = type;
- if (stat_buf.st_size <= 1474560) {
- media->tracks = floppy_type[idx].trk;
- media->heads = floppy_type[idx].hd;
- media->sectors_per_track = floppy_type[idx].spt;
- }
- else if (stat_buf.st_size == 1720320) {
- media->sectors_per_track = 21;
- media->tracks = 80;
- media->heads = 2;
- }
- else if (stat_buf.st_size == 1763328) {
- media->sectors_per_track = 21;
- media->tracks = 82;
- media->heads = 2;
- }
- else {
- BX_INFO(("evaluate_media: file '%s' of unknown size %lu",
- path, (unsigned long) stat_buf.st_size));
- return(0);
- }
- media->sectors = media->heads * media->tracks * media->sectors_per_track;
- }
- return(1); // success
- }
-
- else if ( S_ISCHR(stat_buf.st_mode)
-#if BX_WITH_MACOS == 0
-#ifdef S_ISBLK
- || S_ISBLK(stat_buf.st_mode)
-#endif
-#endif
- ) {
- // character or block device
- // assume media is formatted to typical geometry for drive
- media->type = type;
-#ifdef __linux__
- if (ioctl(media->fd, FDGETPRM, &floppy_geom) < 0) {
- BX_ERROR(("cannot determine media geometry"));
- return(0);
- }
- media->tracks = floppy_geom.track;
- media->heads = floppy_geom.head;
- media->sectors_per_track = floppy_geom.sect;
- media->sectors = floppy_geom.size;
-#elif defined(WIN32)
- media->tracks = tracks;
- media->heads = heads;
- media->sectors_per_track = spt;
- media->sectors = media->heads * media->tracks * media->sectors_per_track;
-#else
- media->tracks = floppy_type[idx].trk;
- media->heads = floppy_type[idx].hd;
- media->sectors_per_track = floppy_type[idx].spt;
- media->sectors = floppy_type[idx].sectors;
-#endif
- return(1); // success
- }
- else {
- // unknown file type
- BX_INFO(("unknown mode type"));
- return(0);
- }
-}
-
-
-void
-bx_floppy_ctrl_c::enter_result_phase(void)
-{
-
- Bit8u drive;
-
- drive = BX_FD_THIS s.DOR & 0x03;
-
- /* these are always the same */
- BX_FD_THIS s.result_index = 0;
- BX_FD_THIS s.main_status_reg = FD_MS_MRQ | FD_MS_DIO | FD_MS_BUSY;
-
- /* invalid command */
- if ((BX_FD_THIS s.status_reg0 & 0xc0) == 0x80) {
- BX_FD_THIS s.result_size = 1;
- BX_FD_THIS s.result[0] = BX_FD_THIS s.status_reg0;
- return;
- }
-
- switch (BX_FD_THIS s.pending_command) {
- case 0x04: // get status
- BX_FD_THIS s.result_size = 1;
- BX_FD_THIS s.result[0] = BX_FD_THIS s.status_reg3;
- break;
- case 0x08: // sense interrupt
- BX_FD_THIS s.result_size = 2;
- BX_FD_THIS s.result[0] = BX_FD_THIS s.status_reg0;
- BX_FD_THIS s.result[1] = BX_FD_THIS s.cylinder[drive];
- break;
- case 0x4a: // read ID
- case 0x4d: // format track
- case 0x46: // read normal data
- case 0x66:
- case 0xc6:
- case 0xe6:
- case 0x45: // write normal data
- case 0xc5:
- BX_FD_THIS s.result_size = 7;
- BX_FD_THIS s.result[0] = BX_FD_THIS s.status_reg0;
- BX_FD_THIS s.result[1] = BX_FD_THIS s.status_reg1;
- BX_FD_THIS s.result[2] = BX_FD_THIS s.status_reg2;
- BX_FD_THIS s.result[3] = BX_FD_THIS s.cylinder[drive];
- BX_FD_THIS s.result[4] = BX_FD_THIS s.head[drive];
- BX_FD_THIS s.result[5] = BX_FD_THIS s.sector[drive];
- BX_FD_THIS s.result[6] = 2; /* sector size code */
- raise_interrupt();
- break;
- }
-}
-
-void
-bx_floppy_ctrl_c::enter_idle_phase(void)
-{
- BX_FD_THIS s.main_status_reg &= 0x0f; // leave drive status untouched
- BX_FD_THIS s.main_status_reg |= FD_MS_MRQ; // data register ready
-
- BX_FD_THIS s.command_complete = 1; /* waiting for new command */
- BX_FD_THIS s.command_index = 0;
- BX_FD_THIS s.command_size = 0;
- BX_FD_THIS s.pending_command = 0;
-
- BX_FD_THIS s.floppy_buffer_index = 0;
-}
-
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: floppy.h,v 1.16 2002/11/30 09:39:29 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-
-#define FROM_FLOPPY 10
-#define TO_FLOPPY 11
-
-#if BX_USE_FD_SMF
-# define BX_FD_SMF static
-# define BX_FD_THIS theFloppyController->
-#else
-# define BX_FD_SMF
-# define BX_FD_THIS this->
-#endif
-
-typedef struct {
- int fd; /* file descriptor of floppy image file */
- unsigned sectors_per_track; /* number of sectors/track */
- unsigned sectors; /* number of formatted sectors on diskette */
- unsigned tracks; /* number of tracks */
- unsigned heads; /* number of heads */
- unsigned type;
- unsigned write_protected;
- } floppy_t;
-
-class bx_floppy_ctrl_c : public bx_floppy_stub_c {
-public:
-
- bx_floppy_ctrl_c(void);
- ~bx_floppy_ctrl_c(void);
- virtual void init(void);
- virtual void reset(unsigned type);
- virtual unsigned set_media_status(unsigned drive, unsigned status);
- virtual unsigned get_media_status(unsigned drive);
-
-private:
-
- struct {
- Bit8u data_rate;
-
- Bit8u command[10]; /* largest command size ??? */
- Bit8u command_index;
- Bit8u command_size;
- bx_bool command_complete;
- Bit8u pending_command;
-
- bx_bool multi_track;
- bx_bool pending_irq;
- Bit8u reset_sensei;
- Bit8u format_count;
- Bit8u format_fillbyte;
-
- Bit8u result[10];
- Bit8u result_index;
- Bit8u result_size;
-
- Bit8u DOR; // Digital Ouput Register
- Bit8u TDR; // Tape Drive Register
- Bit8u cylinder[4]; // really only using 2 drives
- Bit8u head[4]; // really only using 2 drives
- Bit8u sector[4]; // really only using 2 drives
-
- /* MAIN STATUS REGISTER
- * b7: MRQ: main request 1=data register ready 0=data register not ready
- * b6: DIO: data input/output:
- * 1=controller->CPU (ready for data read)
- * 0=CPU->controller (ready for data write)
- * b5: NDMA: non-DMA mode: 1=controller not in DMA modes
- * 0=controller in DMA mode
- * b4: BUSY: instruction(device busy) 1=active 0=not active
- * b3-0: ACTD, ACTC, ACTB, ACTA:
- * drive D,C,B,A in positioning mode 1=active 0=not active
- */
- Bit8u main_status_reg;
-
- Bit8u status_reg0;
- Bit8u status_reg1;
- Bit8u status_reg2;
- Bit8u status_reg3;
-
- // drive field allows up to 4 drives, even though probably only 2 will
- // ever be used.
- floppy_t media[4];
- unsigned num_supported_floppies;
- Bit8u floppy_buffer[512+2]; // 2 extra for good measure
- unsigned floppy_buffer_index;
- int floppy_timer_index;
- bx_bool media_present[2];
- Bit8u device_type[4];
- Bit8u DIR[4]; // Digital Input Register:
- // b7: 0=diskette is present and has not been changed
- // 1=diskette missing or changed
- } s; // state information
-
- static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len);
- static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len);
-#if !BX_USE_FD_SMF
- Bit32u read(Bit32u address, unsigned io_len);
- void write(Bit32u address, Bit32u value, unsigned io_len);
-#endif
- BX_FD_SMF void dma_write(Bit8u *data_byte);
- BX_FD_SMF void dma_read(Bit8u *data_byte);
- BX_FD_SMF void floppy_command(void);
- BX_FD_SMF void floppy_xfer(Bit8u drive, Bit32u offset, Bit8u *buffer, Bit32u bytes, Bit8u direction);
- BX_FD_SMF void raise_interrupt(void);
- BX_FD_SMF void enter_idle_phase(void);
- BX_FD_SMF void enter_result_phase(void);
- static void timer_handler(void *);
-
-public:
- BX_FD_SMF void timer(void);
- BX_FD_SMF void increment_sector(void);
- BX_FD_SMF bx_bool evaluate_media(unsigned type, char *path, floppy_t *floppy);
- };
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: gameport.cc,v 1.5 2003/12/29 21:48:56 cbothamy Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2003 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-//
-// Standard PC gameport
-//
-
-// Define BX_PLUGGABLE in files that can be compiled into plugins. For
-// platforms that require a special tag on exported symbols, BX_PLUGGABLE
-// is used to know when we are exporting symbols and when we are importing.
-#define BX_PLUGGABLE
-
-#include "bochs.h"
-
-#ifdef __linux__
-
-#include <linux/joystick.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <stdio.h>
-
-#elif defined(WIN32)
-
-#ifndef JOY_BUTTON1
-#define JOY_BUTTON1 1
-#define JOY_BUTTON2 2
-UINT STDCALL joyGetPos(UINT, LPJOYINFO);
-#endif
-
-#define JOYSTICKID1 0
-
-#endif
-
-#define LOG_THIS theGameport->
-
-bx_gameport_c *theGameport = NULL;
-
- int
-libgameport_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[])
-{
- theGameport = new bx_gameport_c ();
- bx_devices.pluginGameport = theGameport;
- BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theGameport, BX_PLUGIN_GAMEPORT);
- return(0); // Success
-}
-
- void
-libgameport_LTX_plugin_fini(void)
-{
-}
-
-bx_gameport_c::bx_gameport_c(void)
-{
- put("GAME");
- settype(EXTFPUIRQLOG);
-}
-
-bx_gameport_c::~bx_gameport_c(void)
-{
- if (joyfd >= 0) close(joyfd);
- BX_DEBUG(("Exit."));
-}
-
-
- void
-bx_gameport_c::init(void)
-{
- // Allocate the gameport IO address range 0x200..0x207
- for (unsigned addr=0x200; addr<0x208; addr++) {
- DEV_register_ioread_handler(this, read_handler, addr, "Gameport", 1);
- DEV_register_iowrite_handler(this, write_handler, addr, "Gameport", 1);
- }
-
- BX_GAMEPORT_THIS port = 0xf0;
- BX_GAMEPORT_THIS write_usec = 0;
- BX_GAMEPORT_THIS timer_x = 0;
- BX_GAMEPORT_THIS timer_y = 0;
-
-#ifdef __linux__
- BX_GAMEPORT_THIS joyfd = open("/dev/input/js0", O_RDONLY);
- if (BX_GAMEPORT_THIS joyfd >= 0) {
- for (unsigned i=0; i<4; i++) poll_joydev();
- }
-#elif defined(WIN32)
- JOYINFO joypos;
- if (joyGetPos(JOYSTICKID1, &joypos) == JOYERR_NOERROR) {
- BX_GAMEPORT_THIS joyfd = 1;
- } else {
- BX_GAMEPORT_THIS joyfd = -1;
- }
-#else
- BX_GAMEPORT_THIS joyfd = -1;
-#endif
-}
-
- void
-bx_gameport_c::reset(unsigned type)
-{
- // nothing for now
-}
-
- void
-bx_gameport_c::poll_joydev(void)
-{
-#ifdef __linux__
- struct js_event e;
- fd_set joyfds;
- struct timeval tv;
-
- memset(&tv, 0, sizeof(tv));
- FD_ZERO(&joyfds);
- FD_SET(BX_GAMEPORT_THIS joyfd, &joyfds);
- e.type = 0;
- if (select(BX_GAMEPORT_THIS joyfd+1, &joyfds, NULL, NULL, &tv)) {
- read(BX_GAMEPORT_THIS joyfd, &e, sizeof(struct js_event));
- if (e.type & JS_EVENT_BUTTON) {
- if (e.value == 1) {
- BX_GAMEPORT_THIS port &= ~(0x10 << e.number);
- } else {
- BX_GAMEPORT_THIS port |= (0x10 << e.number);
- }
- }
- if (e.type & JS_EVENT_AXIS) {
- if (e.number == 0) {
- BX_GAMEPORT_THIS delay_x = 25 + ((e.value + 0x8000) / 60);
- }
- if (e.number == 1) {
- BX_GAMEPORT_THIS delay_y = 25 + ((e.value + 0x8000) / 62);
- }
- }
- }
-#elif defined(WIN32)
- JOYINFO joypos;
- if (joyGetPos(JOYSTICKID1, &joypos) == JOYERR_NOERROR) {
- if (joypos.wButtons & JOY_BUTTON1) {
- BX_GAMEPORT_THIS port &= ~0x10;
- } else {
- BX_GAMEPORT_THIS port |= 0x10;
- }
- if (joypos.wButtons & JOY_BUTTON2) {
- BX_GAMEPORT_THIS port &= ~0x20;
- } else {
- BX_GAMEPORT_THIS port |= 0x20;
- }
- BX_GAMEPORT_THIS delay_x = 25 + (joypos.wXpos / 60);
- BX_GAMEPORT_THIS delay_y = 25 + (joypos.wYpos / 60);
- }
-#endif
-}
-
-
- // static IO port read callback handler
- // redirects to non-static class handler to avoid virtual functions
-
- Bit32u
-bx_gameport_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len)
-{
-#if !BX_USE_GAME_SMF
- bx_gameport_c *class_ptr = (bx_gameport_c *) this_ptr;
-
- return( class_ptr->read(address, io_len) );
-}
-
-
- Bit32u
-bx_gameport_c::read(Bit32u address, unsigned io_len)
-{
-#else
- UNUSED(this_ptr);
-#endif // !BX_USE_GAME_SMF
- Bit64u usec;
-
- if (BX_GAMEPORT_THIS joyfd >= 0) {
- poll_joydev();
- usec = bx_pc_system.time_usec();
- if (BX_GAMEPORT_THIS timer_x) {
- if ((usec - BX_GAMEPORT_THIS write_usec) >= BX_GAMEPORT_THIS delay_x) {
- BX_GAMEPORT_THIS port &= 0xfe;
- BX_GAMEPORT_THIS timer_x = 0;
- }
- }
- if (BX_GAMEPORT_THIS timer_y) {
- if ((usec - BX_GAMEPORT_THIS write_usec) >= BX_GAMEPORT_THIS delay_y) {
- BX_GAMEPORT_THIS port &= 0xfd;
- BX_GAMEPORT_THIS timer_y = 0;
- }
- }
- } else {
- BX_DEBUG(("read: joystick not present"));
- }
- return BX_GAMEPORT_THIS port;
-}
-
-
- // static IO port write callback handler
- // redirects to non-static class handler to avoid virtual functions
-
- void
-bx_gameport_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len)
-{
-#if !BX_USE_GAME_SMF
- bx_gameport_c *class_ptr = (bx_gameport_c *) this_ptr;
-
- class_ptr->write(address, value, io_len);
-}
-
- void
-bx_gameport_c::write(Bit32u address, Bit32u value, unsigned io_len)
-{
-#else
- UNUSED(this_ptr);
-#endif // !BX_USE_GAME_SMF
-
- BX_GAMEPORT_THIS write_usec = bx_pc_system.time_usec();
- BX_GAMEPORT_THIS timer_x = 1;
- BX_GAMEPORT_THIS timer_y = 1;
- BX_GAMEPORT_THIS port |= 0x0f;
-}
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: gameport.h,v 1.1 2003/06/21 12:55:19 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2003 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-#if BX_USE_GAME_SMF
-# define BX_GAMEPORT_SMF static
-# define BX_GAMEPORT_THIS theGameport->
-#else
-# define BX_GAMEPORT_SMF
-# define BX_GAMEPORT_THIS this->
-#endif
-
-
-class bx_gameport_c : public bx_devmodel_c {
-
-public:
- bx_gameport_c(void);
- ~bx_gameport_c(void);
- virtual void init(void);
- virtual void reset(unsigned type);
-
-private:
-
- int joyfd;
- Bit8u port;
- Bit16u delay_x;
- Bit16u delay_y;
- bx_bool timer_x;
- bx_bool timer_y;
- Bit64u write_usec;
-
- BX_GAMEPORT_SMF void poll_joydev(void);
-
- static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len);
- static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len);
-#if !BX_USE_GAME_SMF
- Bit32u read(Bit32u address, unsigned io_len);
- void write(Bit32u address, Bit32u value, unsigned io_len);
-#endif
- };
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: guest2host.h,v 1.8 2002/12/06 18:48:08 bdenney Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2001 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-
-#define BX_MAX_G2H_CHANNELS 8
-#define BX_G2H_ERROR ((unsigned) -1)
- // IO port number for this interface. Align on dword boundary.
-#define BX_G2H_PORT 0x2000
- // Magic number which is first dword passed by guest
-#define BX_G2H_MAGIC 0xffeeddcc
- // Number of dwords in packet from guest
-#define BX_G2H_PACKET_SIZE 5
-
-
-
-typedef Bit32u bx_guest_packet_t[BX_G2H_PACKET_SIZE];
-typedef void (*bx_g2h_callback_t)(bx_guest_packet_t *);
-
-
-
-class bx_g2h_c : public logfunctions {
-public:
- bx_g2h_c(void);
- ~bx_g2h_c(void);
- static void init(void);
- void reset (unsigned type);
- unsigned acquire_channel(bx_g2h_callback_t);
- unsigned deacquire_channel(unsigned channel);
-
-private:
-
- static Bit32u inp_handler(void *this_ptr, Bit32u addr, unsigned io_len);
- static void outp_handler(void *this_ptr, Bit32u addr,
- Bit32u value, unsigned io_len);
- // state info
- struct {
- struct {
- bx_g2h_callback_t f;
- bx_bool used;
- } callback[BX_MAX_G2H_CHANNELS];
-
- // Define the data received from the guest OS.
- // dword0: magic number, should be BX_G2H_MAGIC
- // dword1: channel ID
- // dword2: address of data structure in guest physical memory
- // dword3: size of data structure in guest physical memory
- // dword4: address of return data structure in guest physical memory
- unsigned packet_count;
- bx_guest_packet_t guest_packet;
- } s;
- };
-
-extern bx_g2h_c bx_g2h;
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: harddrv.cc,v 1.114.2.2 2004/02/06 22:14:35 danielg4 Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-// Useful docs:
-// AT Attachment with Packet Interface
-// working draft by T13 at www.t13.org
-
-
-
-// Define BX_PLUGGABLE in files that can be compiled into plugins. For
-// platforms that require a special tag on exported symbols, BX_PLUGGABLE
-// is used to know when we are exporting symbols and when we are importing.
-#define BX_PLUGGABLE
-
-#include "bochs.h"
-
-#if BX_HAVE_SYS_MMAN_H
-#include <sys/mman.h>
-#endif
-
-#define LOG_THIS theHardDrive->
-
-// WARNING: dangerous options!
-// These options provoke certain kinds of errors for testing purposes when they
-// are set to a nonzero value. DO NOT ENABLE THEM when using any disk image
-// you care about.
-#define TEST_READ_BEYOND_END 0
-#define TEST_WRITE_BEYOND_END 0
-#ifdef __GNUC__
-# if TEST_READ_BEYOND_END || TEST_WRITE_BEYOND_END
-# warning BEWARE: Dangerous options are enabled in harddrv.cc. If you are not trying to provoke hard drive errors you should disable them right now.
-# endif
-#endif
-// end of dangerous options.
-
-
-#define INDEX_PULSE_CYCLE 10
-
-#define PACKET_SIZE 12
-
-static unsigned max_multiple_sectors = 0; // was 0x3f
-static unsigned curr_multiple_sectors = 0; // was 0x3f
-
-// some packet handling macros
-#define EXTRACT_FIELD(arr,byte,start,num_bits) (((arr)[(byte)] >> (start)) & ((1 << (num_bits)) - 1))
-#define get_packet_field(c,b,s,n) (EXTRACT_FIELD((BX_SELECTED_CONTROLLER((c)).buffer),(b),(s),(n)))
-#define get_packet_byte(c,b) (BX_SELECTED_CONTROLLER((c)).buffer[(b)])
-#define get_packet_word(c,b) (((uint16)BX_SELECTED_CONTROLLER((c)).buffer[(b)] << 8) | BX_SELECTED_CONTROLLER((c)).buffer[(b)+1])
-
-
-#define BX_CONTROLLER(c,a) (BX_HD_THIS channels[(c)].drives[(a)]).controller
-#define BX_DRIVE(c,a) (BX_HD_THIS channels[(c)].drives[(a)])
-
-#define BX_DRIVE_IS_PRESENT(c,a) (BX_HD_THIS channels[(c)].drives[(a)].device_type != IDE_NONE)
-#define BX_DRIVE_IS_HD(c,a) (BX_HD_THIS channels[(c)].drives[(a)].device_type == IDE_DISK)
-#define BX_DRIVE_IS_CD(c,a) (BX_HD_THIS channels[(c)].drives[(a)].device_type == IDE_CDROM)
-
-#define BX_MASTER_IS_PRESENT(c) BX_DRIVE_IS_PRESENT((c),0)
-#define BX_SLAVE_IS_PRESENT(c) BX_DRIVE_IS_PRESENT((c),1)
-#define BX_ANY_IS_PRESENT(c) (BX_DRIVE_IS_PRESENT((c),0) || BX_DRIVE_IS_PRESENT((c),1))
-
-#define BX_SELECTED_CONTROLLER(c) (BX_CONTROLLER((c),BX_HD_THIS channels[(c)].drive_select))
-#define BX_SELECTED_DRIVE(c) (BX_DRIVE((c),BX_HD_THIS channels[(c)].drive_select))
-#define BX_MASTER_SELECTED(c) (!BX_HD_THIS channels[(c)].drive_select)
-#define BX_SLAVE_SELECTED(c) (BX_HD_THIS channels[(c)].drive_select)
-
-#define BX_SELECTED_IS_PRESENT(c) (BX_DRIVE_IS_PRESENT((c),BX_SLAVE_SELECTED((c))))
-#define BX_SELECTED_IS_HD(c) (BX_DRIVE_IS_HD((c),BX_SLAVE_SELECTED((c))))
-#define BX_SELECTED_IS_CD(c) (BX_DRIVE_IS_CD((c),BX_SLAVE_SELECTED((c))))
-
-#define BX_SELECTED_MODEL(c) (BX_HD_THIS channels[(c)].drives[BX_HD_THIS channels[(c)].drive_select].model_no)
-#define BX_SELECTED_TYPE_STRING(channel) ((BX_SELECTED_IS_CD(channel)) ? "CD-ROM" : "DISK")
-
-#define WRITE_FEATURES(c,a) do { uint8 _a = a; BX_CONTROLLER((c),0).features = _a; BX_CONTROLLER((c),1).features = _a; } while(0)
-#define WRITE_SECTOR_COUNT(c,a) do { uint8 _a = a; BX_CONTROLLER((c),0).sector_count = _a; BX_CONTROLLER((c),1).sector_count = _a; } while(0)
-#define WRITE_SECTOR_NUMBER(c,a) do { uint8 _a = a; BX_CONTROLLER((c),0).sector_no = _a; BX_CONTROLLER((c),1).sector_no = _a; } while(0)
-#define WRITE_CYLINDER_LOW(c,a) do { uint8 _a = a; BX_CONTROLLER((c),0).cylinder_no = (BX_CONTROLLER((c),0).cylinder_no & 0xff00) | _a; BX_CONTROLLER((c),1).cylinder_no = (BX_CONTROLLER((c),1).cylinder_no & 0xff00) | _a; } while(0)
-#define WRITE_CYLINDER_HIGH(c,a) do { uint16 _a = a; BX_CONTROLLER((c),0).cylinder_no = (_a << 8) | (BX_CONTROLLER((c),0).cylinder_no & 0xff); BX_CONTROLLER((c),1).cylinder_no = (_a << 8) | (BX_CONTROLLER((c),1).cylinder_no & 0xff); } while(0)
-#define WRITE_HEAD_NO(c,a) do { uint8 _a = a; BX_CONTROLLER((c),0).head_no = _a; BX_CONTROLLER((c),1).head_no = _a; } while(0)
-#define WRITE_LBA_MODE(c,a) do { uint8 _a = a; BX_CONTROLLER((c),0).lba_mode = _a; BX_CONTROLLER((c),1).lba_mode = _a; } while(0)
-
-bx_hard_drive_c *theHardDrive = NULL;
-
- int
-libharddrv_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[])
-{
- theHardDrive = new bx_hard_drive_c ();
- bx_devices.pluginHardDrive = theHardDrive;
- BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theHardDrive, BX_PLUGIN_HARDDRV);
- return(0); // Success
-}
-
- void
-libharddrv_LTX_plugin_fini(void)
-{
-}
-
-bx_hard_drive_c::bx_hard_drive_c(void)
-{
-#if DLL_HD_SUPPORT
-# error code must be fixed to use DLL_HD_SUPPORT and 4 ata channels
-#endif
-
- for (Bit8u channel=0; channel<BX_MAX_ATA_CHANNEL; channel++) {
- channels[channel].drives[0].hard_drive = NULL;
- channels[channel].drives[1].hard_drive = NULL;
- put("HD");
- settype(HDLOG);
- }
-}
-
-
-bx_hard_drive_c::~bx_hard_drive_c(void)
-{
- BX_DEBUG(("Exit."));
- for (Bit8u channel=0; channel<BX_MAX_ATA_CHANNEL; channel++) {
- if (channels[channel].drives[0].hard_drive != NULL ) /* DT 17.12.2001 21:55 */
- {
- delete channels[channel].drives[0].hard_drive;
- channels[channel].drives[0].hard_drive = NULL;
- }
- if ( channels[channel].drives[1].hard_drive != NULL )
- {
- delete channels[channel].drives[1].hard_drive;
- channels[channel].drives[1].hard_drive = NULL; /* DT 17.12.2001 21:56 */
- }
- }
-}
-
-
-
-
- void
-bx_hard_drive_c::init(void)
-{
- Bit8u channel;
- char string[5];
-
- BX_DEBUG(("Init $Id: harddrv.cc,v 1.114.2.2 2004/02/06 22:14:35 danielg4 Exp $"));
-
- for (channel=0; channel<BX_MAX_ATA_CHANNEL; channel++) {
- if (bx_options.ata[channel].Opresent->get() == 1) {
- BX_HD_THIS channels[channel].ioaddr1 = bx_options.ata[channel].Oioaddr1->get();
- BX_HD_THIS channels[channel].ioaddr2 = bx_options.ata[channel].Oioaddr2->get();
- BX_HD_THIS channels[channel].irq = bx_options.ata[channel].Oirq->get();
-
- // Coherency check
- if ( (BX_HD_THIS channels[channel].ioaddr1 == 0) ||
- (BX_HD_THIS channels[channel].ioaddr2 == 0) ||
- (BX_HD_THIS channels[channel].irq == 0) ) {
- BX_PANIC(("incoherency for ata channel %d: io1=0x%x, io2=%x, irq=%d",
- channel,
- BX_HD_THIS channels[channel].ioaddr1,
- BX_HD_THIS channels[channel].ioaddr2,
- BX_HD_THIS channels[channel].irq));
- }
- }
- else {
- BX_HD_THIS channels[channel].ioaddr1 = 0;
- BX_HD_THIS channels[channel].ioaddr2 = 0;
- BX_HD_THIS channels[channel].irq = 0;
- }
- }
-
- for (channel=0; channel<BX_MAX_ATA_CHANNEL; channel++) {
- sprintf(string ,"ATA%d", channel);
-
- if (BX_HD_THIS channels[channel].irq != 0)
- DEV_register_irq(BX_HD_THIS channels[channel].irq, strdup(string));
-
- if (BX_HD_THIS channels[channel].ioaddr1 != 0) {
- DEV_register_ioread_handler(this, read_handler,
- BX_HD_THIS channels[channel].ioaddr1, strdup(string), 6);
- DEV_register_iowrite_handler(this, write_handler,
- BX_HD_THIS channels[channel].ioaddr1, strdup(string), 6);
- for (unsigned addr=0x1; addr<=0x7; addr++) {
- DEV_register_ioread_handler(this, read_handler,
- BX_HD_THIS channels[channel].ioaddr1+addr, strdup(string), 1);
- DEV_register_iowrite_handler(this, write_handler,
- BX_HD_THIS channels[channel].ioaddr1+addr, strdup(string), 1);
- }
- }
-
- // We don't want to register addresses 0x3f6 and 0x3f7 as they are handled by the floppy controller
- if ((BX_HD_THIS channels[channel].ioaddr2 != 0) && (BX_HD_THIS channels[channel].ioaddr2 != 0x3f0)) {
- for (unsigned addr=0x6; addr<=0x7; addr++) {
- DEV_register_ioread_handler(this, read_handler,
- BX_HD_THIS channels[channel].ioaddr2+addr, strdup(string), 1);
- DEV_register_iowrite_handler(this, write_handler,
- BX_HD_THIS channels[channel].ioaddr2+addr, strdup(string), 1);
- }
- }
-
- BX_HD_THIS channels[channel].drive_select = 0;
- }
-
- channel = 0;
- for (channel=0; channel<BX_MAX_ATA_CHANNEL; channel++) {
- for (Bit8u device=0; device<2; device ++) {
-
- // Initialize controller state, even if device is not present
- BX_CONTROLLER(channel,device).status.busy = 0;
- BX_CONTROLLER(channel,device).status.drive_ready = 1;
- BX_CONTROLLER(channel,device).status.write_fault = 0;
- BX_CONTROLLER(channel,device).status.seek_complete = 1;
- BX_CONTROLLER(channel,device).status.drq = 0;
- BX_CONTROLLER(channel,device).status.corrected_data = 0;
- BX_CONTROLLER(channel,device).status.index_pulse = 0;
- BX_CONTROLLER(channel,device).status.index_pulse_count = 0;
- BX_CONTROLLER(channel,device).status.err = 0;
-
- BX_CONTROLLER(channel,device).error_register = 0x01; // diagnostic code: no error
- BX_CONTROLLER(channel,device).head_no = 0;
- BX_CONTROLLER(channel,device).sector_count = 1;
- BX_CONTROLLER(channel,device).sector_no = 1;
- BX_CONTROLLER(channel,device).cylinder_no = 0;
- BX_CONTROLLER(channel,device).current_command = 0x00;
- BX_CONTROLLER(channel,device).buffer_index = 0;
-
- BX_CONTROLLER(channel,device).control.reset = 0;
- BX_CONTROLLER(channel,device).control.disable_irq = 0;
- BX_CONTROLLER(channel,device).reset_in_progress = 0;
-
- BX_CONTROLLER(channel,device).sectors_per_block = 0x80;
- BX_CONTROLLER(channel,device).lba_mode = 0;
-
- BX_CONTROLLER(channel,device).features = 0;
-
- // If not present
- BX_HD_THIS channels[channel].drives[device].device_type = IDE_NONE;
- if (!bx_options.atadevice[channel][device].Opresent->get()) {
- continue;
- }
-
- // Make model string
- strncpy((char*)BX_HD_THIS channels[channel].drives[device].model_no,
- bx_options.atadevice[channel][device].Omodel->getptr(), 40);
- while (strlen((char *)BX_HD_THIS channels[channel].drives[device].model_no) < 40) {
- strcat ((char*)BX_HD_THIS channels[channel].drives[device].model_no, " ");
- }
-
- if (bx_options.atadevice[channel][device].Otype->get() == BX_ATA_DEVICE_DISK) {
- BX_DEBUG(( "Hard-Disk on target %d/%d",channel,device));
- BX_HD_THIS channels[channel].drives[device].device_type = IDE_DISK;
-
- int cyl = bx_options.atadevice[channel][device].Ocylinders->get ();
- int heads = bx_options.atadevice[channel][device].Oheads->get ();
- int spt = bx_options.atadevice[channel][device].Ospt->get ();
- Bit64u disk_size = (Bit64u)cyl * heads * spt * 512;
-
- /* instantiate the right class */
- switch (bx_options.atadevice[channel][device].Omode->get()) {
-
- case BX_ATA_MODE_FLAT:
- BX_INFO(("HD on ata%d-%d: '%s' 'flat' mode ", channel, device,
- bx_options.atadevice[channel][device].Opath->getptr ()));
- channels[channel].drives[device].hard_drive = new default_image_t();
- break;
-
- case BX_ATA_MODE_CONCAT:
- BX_INFO(("HD on ata%d-%d: '%s' 'concat' mode ", channel, device,
- bx_options.atadevice[channel][device].Opath->getptr ()));
- channels[channel].drives[device].hard_drive = new concat_image_t();
- break;
-
-#if EXTERNAL_DISK_SIMULATOR
- case BX_ATA_MODE_EXTDISKSIM:
- BX_INFO(("HD on ata%d-%d: '%s' 'External Simulator' mode ", channel, device,
- bx_options.atadevice[channel][device].Opath->getptr ()));
- channels[channel].drives[device].hard_drive = new EXTERNAL_DISK_SIMULATOR_CLASS();
- break;
-#endif //EXTERNAL_DISK_SIMULATOR
-
-#if DLL_HD_SUPPORT
- case BX_ATA_MODE_DLL_HD:
- BX_INFO(("HD on ata%d-%d: '%s' 'dll' mode ", channel, device,
- bx_options.atadevice[channel][device].Opath->getptr ()));
- channels[channel].drives[device].hard_drive = new dll_image_t();
- break;
-#endif //DLL_HD_SUPPORT
-
- case BX_ATA_MODE_SPARSE:
- BX_INFO(("HD on ata%d-%d: '%s' 'sparse' mode ", channel, device,
- bx_options.atadevice[channel][device].Opath->getptr ()));
- channels[channel].drives[device].hard_drive = new sparse_image_t();
- break;
-
-#if 0
- case BX_ATA_MODE_VMWARE3:
- BX_INFO(("HD on ata%d-%d: '%s' 'vmware3' mode ", channel, device,
- bx_options.atadevice[channel][device].Opath->getptr ()));
- channels[channel].drives[device].hard_drive = new vmware3_image_t();
- break;
-
- case BX_ATA_MODE_SPLIT:
- BX_INFO(("HD on ata%d-%d: '%s' 'split' mode ", channel, device,
- bx_options.atadevice[channel][device].Opath->getptr ()));
- channels[channel].drives[device].hard_drive = new split_image_t();
- break;
-#endif
-
- case BX_ATA_MODE_UNDOABLE:
- BX_INFO(("HD on ata%d-%d: '%s' 'undoable' mode ", channel, device,
- bx_options.atadevice[channel][device].Opath->getptr ()));
- channels[channel].drives[device].hard_drive = new undoable_image_t(disk_size,
- bx_options.atadevice[channel][device].Ojournal->getptr());
- break;
-
- case BX_ATA_MODE_GROWING:
- BX_INFO(("HD on ata%d-%d: '%s' 'growing' mode ", channel, device,
- bx_options.atadevice[channel][device].Opath->getptr ()));
- channels[channel].drives[device].hard_drive = new growing_image_t(disk_size);
- break;
-
- case BX_ATA_MODE_VOLATILE:
- BX_INFO(("HD on ata%d-%d: '%s' 'volatile' mode ", channel, device,
- bx_options.atadevice[channel][device].Opath->getptr ()));
- channels[channel].drives[device].hard_drive = new volatile_image_t(disk_size,
- bx_options.atadevice[channel][device].Ojournal->getptr());
- break;
-
-#if 0
-#if BX_COMPRESSED_HD_SUPPORT
- case BX_ATA_MODE_Z_UNDOABLE:
- BX_PANIC(("z-undoable disk support not implemented"));
- BX_INFO(("HD on ata%d-%d: '%s' 'z-undoable' mode ", channel, device,
- bx_options.atadevice[channel][device].Opath->getptr ()));
- channels[channel].drives[device].hard_drive = new z_undoable_image_t(disk_size,
- bx_options.atadevice[channel][device].Ojournal->getptr());
- break;
-
- case BX_ATA_MODE_Z_VOLATILE:
- BX_PANIC(("z-volatile disk support not implemented"));
- BX_INFO(("HD on ata%d-%d: '%s' 'z-volatile' mode ", channel, device,
- bx_options.atadevice[channel][device].Opath->getptr ()));
- channels[channel].drives[device].hard_drive = new z_volatile_image_t(disk_size,
- bx_options.atadevice[channel][device].Ojournal->getptr());
- break;
-#endif //BX_COMPRESSED_HD_SUPPORT
-#endif
-
- default:
- BX_PANIC(("HD on ata%d-%d: '%s' unsupported HD mode : %s", channel, device,
- bx_options.atadevice[channel][device].Opath->getptr (),
- atadevice_mode_names[bx_options.atadevice[channel][device].Omode->get()]));
- break;
- }
-
- BX_HD_THIS channels[channel].drives[device].hard_drive->cylinders = cyl;
- BX_HD_THIS channels[channel].drives[device].hard_drive->heads = heads;
- BX_HD_THIS channels[channel].drives[device].hard_drive->sectors = spt;
-
- if (cyl == 0 || heads == 0 || spt == 0) {
- BX_PANIC(("ata%d/%d cannot have zero cylinders, heads, or sectors/track", channel, device));
- }
-
- /* open hard drive image file */
- if ((BX_HD_THIS channels[channel].drives[device].hard_drive->open(bx_options.atadevice[channel][device].Opath->getptr ())) < 0) {
- BX_PANIC(("ata%d-%d: could not open hard drive image file '%s'", channel, device, bx_options.atadevice[channel][device].Opath->getptr ()));
- }
- }
- else if (bx_options.atadevice[channel][device].Otype->get() == BX_ATA_DEVICE_CDROM) {
- BX_DEBUG(( "CDROM on target %d/%d",channel,device));
- BX_HD_THIS channels[channel].drives[device].device_type = IDE_CDROM;
- BX_HD_THIS channels[channel].drives[device].cdrom.locked = 0;
- BX_HD_THIS channels[channel].drives[device].sense.sense_key = SENSE_NONE;
- BX_HD_THIS channels[channel].drives[device].sense.asc = 0;
- BX_HD_THIS channels[channel].drives[device].sense.ascq = 0;
-
- // Check bit fields
- BX_CONTROLLER(channel,device).sector_count = 0;
- BX_CONTROLLER(channel,device).interrupt_reason.c_d = 1;
- if (BX_CONTROLLER(channel,device).sector_count != 0x01)
- BX_PANIC(("interrupt reason bit field error"));
-
- BX_CONTROLLER(channel,device).sector_count = 0;
- BX_CONTROLLER(channel,device).interrupt_reason.i_o = 1;
- if (BX_CONTROLLER(channel,device).sector_count != 0x02)
- BX_PANIC(("interrupt reason bit field error"));
-
- BX_CONTROLLER(channel,device).sector_count = 0;
- BX_CONTROLLER(channel,device).interrupt_reason.rel = 1;
- if (BX_CONTROLLER(channel,device).sector_count != 0x04)
- BX_PANIC(("interrupt reason bit field error"));
-
- BX_CONTROLLER(channel,device).sector_count = 0;
- BX_CONTROLLER(channel,device).interrupt_reason.tag = 3;
- if (BX_CONTROLLER(channel,device).sector_count != 0x18)
- BX_PANIC(("interrupt reason bit field error"));
- BX_CONTROLLER(channel,device).sector_count = 0;
-
- // allocate low level driver
-#ifdef LOWLEVEL_CDROM
- BX_HD_THIS channels[channel].drives[device].cdrom.cd = new LOWLEVEL_CDROM(bx_options.atadevice[channel][device].Opath->getptr ());
- BX_INFO(("CD on ata%d-%d: '%s'",channel, device, bx_options.atadevice[channel][device].Opath->getptr ()));
-
- if (bx_options.atadevice[channel][device].Ostatus->get () == BX_INSERTED) {
- if (BX_HD_THIS channels[channel].drives[device].cdrom.cd->insert_cdrom()) {
- BX_INFO(( "Media present in CD-ROM drive"));
- BX_HD_THIS channels[channel].drives[device].cdrom.ready = 1;
- BX_HD_THIS channels[channel].drives[device].cdrom.capacity = BX_HD_THIS channels[channel].drives[device].cdrom.cd->capacity();
- } else {
- BX_INFO(( "Could not locate CD-ROM, continuing with media not present"));
- BX_HD_THIS channels[channel].drives[device].cdrom.ready = 0;
- bx_options.atadevice[channel][device].Ostatus->set(BX_EJECTED);
- }
- } else {
-#endif
- BX_INFO(( "Media not present in CD-ROM drive" ));
- BX_HD_THIS channels[channel].drives[device].cdrom.ready = 0;
-#ifdef LOWLEVEL_CDROM
- }
-#endif
- }
- }
- }
-
-#if BX_PDC20230C_VLBIDE_SUPPORT
- BX_HD_THIS pdc20230c.prog_mode = 0;
- BX_HD_THIS pdc20230c.prog_count = 0;
- BX_HD_THIS pdc20230c.p1f3_value = 0;
- BX_HD_THIS pdc20230c.p1f4_value = 0;
-#endif
-
-
- // generate CMOS values for hard drive if not using a CMOS image
- if (!bx_options.cmos.OcmosImage->get ()) {
- DEV_cmos_set_reg(0x12, 0x00); // start out with: no drive 0, no drive 1
-
- if (BX_DRIVE_IS_HD(0,0)) {
- // Flag drive type as Fh, use extended CMOS location as real type
- DEV_cmos_set_reg(0x12, (DEV_cmos_get_reg(0x12) & 0x0f) | 0xf0);
- DEV_cmos_set_reg(0x19, 47); // user definable type
- // AMI BIOS: 1st hard disk #cyl low byte
- DEV_cmos_set_reg(0x1b, (bx_options.atadevice[0][0].Ocylinders->get () & 0x00ff));
- // AMI BIOS: 1st hard disk #cyl high byte
- DEV_cmos_set_reg(0x1c, (bx_options.atadevice[0][0].Ocylinders->get () & 0xff00) >> 8);
- // AMI BIOS: 1st hard disk #heads
- DEV_cmos_set_reg(0x1d, (bx_options.atadevice[0][0].Oheads->get ()));
- // AMI BIOS: 1st hard disk write precompensation cylinder, low byte
- DEV_cmos_set_reg(0x1e, 0xff); // -1
- // AMI BIOS: 1st hard disk write precompensation cylinder, high byte
- DEV_cmos_set_reg(0x1f, 0xff); // -1
- // AMI BIOS: 1st hard disk control byte
- DEV_cmos_set_reg(0x20, (0xc0 | ((bx_options.atadevice[0][0].Oheads->get () > 8) << 3)));
- // AMI BIOS: 1st hard disk landing zone, low byte
- DEV_cmos_set_reg(0x21, DEV_cmos_get_reg(0x1b));
- // AMI BIOS: 1st hard disk landing zone, high byte
- DEV_cmos_set_reg(0x22, DEV_cmos_get_reg(0x1c));
- // AMI BIOS: 1st hard disk sectors/track
- DEV_cmos_set_reg(0x23, bx_options.atadevice[0][0].Ospt->get ());
- }
-
- //set up cmos for second hard drive
- if (BX_DRIVE_IS_HD(0,1)) {
- BX_DEBUG(("1: I will put 0xf into the second hard disk field"));
- // fill in lower 4 bits of 0x12 for second HD
- DEV_cmos_set_reg(0x12, (DEV_cmos_get_reg(0x12) & 0xf0) | 0x0f);
- DEV_cmos_set_reg(0x1a, 47); // user definable type
- // AMI BIOS: 2nd hard disk #cyl low byte
- DEV_cmos_set_reg(0x24, (bx_options.atadevice[0][1].Ocylinders->get () & 0x00ff));
- // AMI BIOS: 2nd hard disk #cyl high byte
- DEV_cmos_set_reg(0x25, (bx_options.atadevice[0][1].Ocylinders->get () & 0xff00) >> 8);
- // AMI BIOS: 2nd hard disk #heads
- DEV_cmos_set_reg(0x26, (bx_options.atadevice[0][1].Oheads->get ()));
- // AMI BIOS: 2nd hard disk write precompensation cylinder, low byte
- DEV_cmos_set_reg(0x27, 0xff); // -1
- // AMI BIOS: 2nd hard disk write precompensation cylinder, high byte
- DEV_cmos_set_reg(0x28, 0xff); // -1
- // AMI BIOS: 2nd hard disk, 0x80 if heads>8
- DEV_cmos_set_reg(0x29, (bx_options.atadevice[0][1].Oheads->get () > 8) ? 0x80 : 0x00);
- // AMI BIOS: 2nd hard disk landing zone, low byte
- DEV_cmos_set_reg(0x2a, DEV_cmos_get_reg(0x24));
- // AMI BIOS: 2nd hard disk landing zone, high byte
- DEV_cmos_set_reg(0x2b, DEV_cmos_get_reg(0x25));
- // AMI BIOS: 2nd hard disk sectors/track
- DEV_cmos_set_reg(0x2c, bx_options.atadevice[0][1].Ospt->get ());
- }
-
- DEV_cmos_set_reg(0x39, 0);
- DEV_cmos_set_reg(0x3a, 0);
- for (channel=0; channel<BX_MAX_ATA_CHANNEL; channel++) {
- for (Bit8u device=0; device<2; device ++) {
- if (bx_options.atadevice[channel][device].Opresent->get()) {
- if (BX_DRIVE_IS_HD(channel,device)) {
- Bit16u cylinders = bx_options.atadevice[channel][device].Ocylinders->get();
- Bit16u heads = bx_options.atadevice[channel][device].Oheads->get();
- Bit16u spt = bx_options.atadevice[channel][device].Ospt->get();
- Bit8u translation = bx_options.atadevice[channel][device].Otranslation->get();
-
- Bit8u reg = 0x39 + channel/2;
- Bit8u bitshift = 2 * (device+(2 * (channel%2)));
-
- // Find the right translation if autodetect
- if (translation == BX_ATA_TRANSLATION_AUTO) {
- if((cylinders <= 1024) && (heads <= 16) && (spt <= 63)) {
- translation = BX_ATA_TRANSLATION_NONE;
- }
- else if (((Bit32u)cylinders * (Bit32u)heads) <= 131072) {
- translation = BX_ATA_TRANSLATION_LARGE;
- }
- else translation = BX_ATA_TRANSLATION_LBA;
-
- BX_INFO(("translation on ata%d-%d set to '%s'",channel, device,
- translation==BX_ATA_TRANSLATION_NONE?"none":
- translation==BX_ATA_TRANSLATION_LARGE?"large":
- "lba"));
- }
-
- // FIXME we should test and warn
- // - if LBA and spt != 63
- // - if RECHS and heads != 16
- // - if NONE and size > 1024*16*SPT blocks
- // - if LARGE and size > 8192*16*SPT blocks
- // - if RECHS and size > 1024*240*SPT blocks
- // - if LBA and size > 1024*255*63, not that we can do much about it
-
- switch(translation) {
- case BX_ATA_TRANSLATION_NONE:
- DEV_cmos_set_reg(reg, DEV_cmos_get_reg(reg) | (0 << bitshift));
- break;
- case BX_ATA_TRANSLATION_LBA:
- DEV_cmos_set_reg(reg, DEV_cmos_get_reg(reg) | (1 << bitshift));
- break;
- case BX_ATA_TRANSLATION_LARGE:
- DEV_cmos_set_reg(reg, DEV_cmos_get_reg(reg) | (2 << bitshift));
- break;
- case BX_ATA_TRANSLATION_RECHS:
- DEV_cmos_set_reg(reg, DEV_cmos_get_reg(reg) | (3 << bitshift));
- break;
- }
- }
- }
- }
- }
-
- // Set the "non-extended" boot device. This will default to DISKC if cdrom
- if ( bx_options.Obootdrive->get () != BX_BOOT_FLOPPYA) {
- // system boot sequence C:, A:
- DEV_cmos_set_reg(0x2d, DEV_cmos_get_reg(0x2d) & 0xdf);
- }
- else { // 'a'
- // system boot sequence A:, C:
- DEV_cmos_set_reg(0x2d, DEV_cmos_get_reg(0x2d) | 0x20);
- }
-
- // Set the "extended" boot device, byte 0x3D (needed for cdrom booting)
- if ( bx_options.Obootdrive->get () == BX_BOOT_FLOPPYA) {
- // system boot sequence A:
- DEV_cmos_set_reg(0x3d, 0x01);
- BX_INFO(("Boot device will be 'a'"));
- }
- else if ( bx_options.Obootdrive->get () == BX_BOOT_DISKC) {
- // system boot sequence C:
- DEV_cmos_set_reg(0x3d, 0x02);
- BX_INFO(("Boot device will be 'c'"));
- }
- else if ( bx_options.Obootdrive->get () == BX_BOOT_CDROM) {
- // system boot sequence cdrom
- DEV_cmos_set_reg(0x3d, 0x03);
- BX_INFO(("Boot device will be 'cdrom'"));
- }
-
- // Set the signature check flag in cmos, inverted for compatibility
- DEV_cmos_set_reg(0x38, bx_options.OfloppySigCheck->get());
- BX_INFO(("Floppy boot signature check is %sabled", bx_options.OfloppySigCheck->get() ? "dis" : "en"));
- }
-
-}
-
- void
-bx_hard_drive_c::reset(unsigned type)
-{
- for (unsigned channel=0; channel<BX_MAX_ATA_CHANNEL; channel++) {
- if (BX_HD_THIS channels[channel].irq)
- DEV_pic_lower_irq(BX_HD_THIS channels[channel].irq);
- }
-}
-
-
-#define GOTO_RETURN_VALUE if(io_len==4){\
- goto return_value32;\
- }\
- else if(io_len==2){\
- value16=(Bit16u)value32;\
- goto return_value16;\
- }\
- else{\
- value8=(Bit8u)value32;\
- goto return_value8;\
- }
-
-
- // static IO port read callback handler
- // redirects to non-static class handler to avoid virtual functions
-
- Bit32u
-bx_hard_drive_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len)
-{
-#if !BX_USE_HD_SMF
- bx_hard_drive_c *class_ptr = (bx_hard_drive_c *) this_ptr;
-
- return( class_ptr->read(address, io_len) );
-}
-
-
- Bit32u
-bx_hard_drive_c::read(Bit32u address, unsigned io_len)
-{
-#else
- UNUSED(this_ptr);
-#endif // !BX_USE_HD_SMF
- Bit8u value8;
- Bit16u value16;
- Bit32u value32;
-
- Bit8u channel = BX_MAX_ATA_CHANNEL;
- Bit32u port = 0xff; // undefined
-
- for (channel=0; channel<BX_MAX_ATA_CHANNEL; channel++) {
- if ((address & 0xfff8) == BX_HD_THIS channels[channel].ioaddr1) {
- port = address - BX_HD_THIS channels[channel].ioaddr1;
- break;
- }
- else if ((address & 0xfff8) == BX_HD_THIS channels[channel].ioaddr2) {
- port = address - BX_HD_THIS channels[channel].ioaddr2 + 0x10;
- break;
- }
- }
-
- if (channel == BX_MAX_ATA_CHANNEL) {
- if ((address < 0x03f6) || (address > 0x03f7)) {
- BX_PANIC(("read: unable to find ATA channel, ioport=0x%04x", address));
- } else {
- channel = 0;
- port = address - 0x03e0;
- }
- }
-
-#if BX_PDC20230C_VLBIDE_SUPPORT
-// pdc20230c is only available for first ata channel
-if (channel == 0) {
-
- // Detect the switch to programming mode
- if (!BX_HD_THIS pdc20230c.prog_mode) {
- switch (port) {
- case 0x02:
- if ((BX_HD_THIS pdc20230c.prog_count == 0) || (BX_HD_THIS pdc20230c.prog_count > 2)) {
- BX_HD_THIS pdc20230c.prog_count++;
- }
- else {
- BX_HD_THIS pdc20230c.prog_count=0;
- }
- break;
- case 0x16:
- if ((BX_HD_THIS pdc20230c.prog_count == 1) || (BX_HD_THIS pdc20230c.prog_count == 2)) {
- BX_HD_THIS pdc20230c.prog_count++;
- }
- else {
- BX_HD_THIS pdc20230c.prog_count=0;
- }
- break;
- default:
- BX_HD_THIS pdc20230c.prog_count=0;
- }
-
- if (BX_HD_THIS pdc20230c.prog_count == 5) {
- BX_HD_THIS pdc20230c.prog_mode = 1;
- BX_SELECTED_CONTROLLER(channel).sector_count &= 0x7f;
- BX_INFO(("Promise VLB-IDE DC2300: Switching to Programming mode"));
- }
- }
-
- // Returns value when in programming mode
- if (BX_HD_THIS pdc20230c.prog_mode) {
- switch (port) {
- case 0x05:
- // Leave programming mode
- BX_HD_THIS pdc20230c.prog_mode = 0;
- BX_INFO(("Promise VLB-IDE DC2300: Leaving Programming mode"));
- // Value will be sent be normal code
- break;
- case 0x03:
- // Special programming register
- value32 = BX_HD_THIS pdc20230c.p1f3_value;
- GOTO_RETURN_VALUE ;
- break;
- case 0x04:
- // Special programming register
- value32 = BX_HD_THIS pdc20230c.p1f4_value;
- GOTO_RETURN_VALUE ;
- break;
- }
- }
-}
-#endif
-
- switch (port) {
- case 0x00: // hard disk data (16bit) 0x1f0
- if (BX_SELECTED_CONTROLLER(channel).status.drq == 0) {
- BX_ERROR(("IO read(0x%04x) with drq == 0: last command was %02xh",
- address, (unsigned) BX_SELECTED_CONTROLLER(channel).current_command));
- return(0);
- }
- BX_DEBUG(("IO read(0x%04x): current command is %02xh",
- address, (unsigned) BX_SELECTED_CONTROLLER(channel).current_command));
- switch (BX_SELECTED_CONTROLLER(channel).current_command) {
- case 0x20: // READ SECTORS, with retries
- case 0x21: // READ SECTORS, without retries
- if (BX_SELECTED_CONTROLLER(channel).buffer_index >= 512)
- BX_PANIC(("IO read(0x%04x): buffer_index >= 512", address));
-
-#if BX_SupportRepeatSpeedups
- if (DEV_bulk_io_quantum_requested()) {
- unsigned transferLen, quantumsMax;
-
- quantumsMax =
- (512 - BX_SELECTED_CONTROLLER(channel).buffer_index) / io_len;
- if ( quantumsMax == 0)
- BX_PANIC(("IO read(0x%04x): not enough space for read", address));
- DEV_bulk_io_quantum_transferred() =
- DEV_bulk_io_quantum_requested();
- if (quantumsMax < DEV_bulk_io_quantum_transferred())
- DEV_bulk_io_quantum_transferred() = quantumsMax;
- transferLen = io_len * DEV_bulk_io_quantum_transferred();
- memcpy((Bit8u*) DEV_bulk_io_host_addr(),
- &BX_SELECTED_CONTROLLER(channel).buffer[BX_SELECTED_CONTROLLER(channel).buffer_index],
- transferLen);
- DEV_bulk_io_host_addr() += transferLen;
- BX_SELECTED_CONTROLLER(channel).buffer_index += transferLen;
- value32 = 0; // Value returned not important;
- }
- else
-#endif
- {
- value32 = 0L;
- switch(io_len){
- case 4:
- value32 |= (BX_SELECTED_CONTROLLER(channel).buffer[BX_SELECTED_CONTROLLER(channel).buffer_index+3] << 24);
- value32 |= (BX_SELECTED_CONTROLLER(channel).buffer[BX_SELECTED_CONTROLLER(channel).buffer_index+2] << 16);
- case 2:
- value32 |= (BX_SELECTED_CONTROLLER(channel).buffer[BX_SELECTED_CONTROLLER(channel).buffer_index+1] << 8);
- value32 |= BX_SELECTED_CONTROLLER(channel).buffer[BX_SELECTED_CONTROLLER(channel).buffer_index];
- }
- BX_SELECTED_CONTROLLER(channel).buffer_index += io_len;
- }
-
- // if buffer completely read
- if (BX_SELECTED_CONTROLLER(channel).buffer_index >= 512) {
- // update sector count, sector number, cylinder,
- // drive, head, status
- // if there are more sectors, read next one in...
- //
- BX_SELECTED_CONTROLLER(channel).buffer_index = 0;
-
- increment_address(channel);
-
- BX_SELECTED_CONTROLLER(channel).status.busy = 0;
- BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1;
- BX_SELECTED_CONTROLLER(channel).status.write_fault = 0;
- if (bx_options.OnewHardDriveSupport->get ())
- BX_SELECTED_CONTROLLER(channel).status.seek_complete = 1;
- else
- BX_SELECTED_CONTROLLER(channel).status.seek_complete = 0;
- BX_SELECTED_CONTROLLER(channel).status.corrected_data = 0;
- BX_SELECTED_CONTROLLER(channel).status.err = 0;
-
- if (BX_SELECTED_CONTROLLER(channel).sector_count==0) {
- BX_SELECTED_CONTROLLER(channel).status.drq = 0;
- }
- else { /* read next one into controller buffer */
- off_t logical_sector;
- off_t ret;
-
- BX_SELECTED_CONTROLLER(channel).status.drq = 1;
- BX_SELECTED_CONTROLLER(channel).status.seek_complete = 1;
-
-#if TEST_READ_BEYOND_END==1
- BX_SELECTED_CONTROLLER(channel).cylinder_no += 100000;
-#endif
- if (!calculate_logical_address(channel, &logical_sector)) {
- BX_ERROR(("multi-sector read reached invalid sector %lu, aborting", (unsigned long)logical_sector));
- command_aborted (channel, BX_SELECTED_CONTROLLER(channel).current_command);
- GOTO_RETURN_VALUE ;
- }
- ret = BX_SELECTED_DRIVE(channel).hard_drive->lseek(logical_sector * 512, SEEK_SET);
- if (ret < 0) {
- BX_ERROR(("could not lseek() hard drive image file"));
- command_aborted (channel, BX_SELECTED_CONTROLLER(channel).current_command);
- GOTO_RETURN_VALUE ;
- }
- ret = BX_SELECTED_DRIVE(channel).hard_drive->read((bx_ptr_t) BX_SELECTED_CONTROLLER(channel).buffer, 512);
- if (ret < 512) {
- BX_ERROR(("logical sector was %lu", (unsigned long)logical_sector));
- BX_ERROR(("could not read() hard drive image file at byte %lu", (unsigned long)logical_sector*512));
- command_aborted (channel, BX_SELECTED_CONTROLLER(channel).current_command);
- GOTO_RETURN_VALUE ;
- }
-
- BX_SELECTED_CONTROLLER(channel).buffer_index = 0;
- raise_interrupt(channel);
- }
- }
- GOTO_RETURN_VALUE ;
- break;
-
- case 0xec: // IDENTIFY DEVICE
- case 0xa1:
- if (bx_options.OnewHardDriveSupport->get ()) {
- unsigned index;
-
- BX_SELECTED_CONTROLLER(channel).status.busy = 0;
- BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1;
- BX_SELECTED_CONTROLLER(channel).status.write_fault = 0;
- BX_SELECTED_CONTROLLER(channel).status.seek_complete = 1;
- BX_SELECTED_CONTROLLER(channel).status.corrected_data = 0;
- BX_SELECTED_CONTROLLER(channel).status.err = 0;
-
- index = BX_SELECTED_CONTROLLER(channel).buffer_index;
- value32 = BX_SELECTED_CONTROLLER(channel).buffer[index];
- index++;
- if (io_len >= 2) {
- value32 |= (BX_SELECTED_CONTROLLER(channel).buffer[index] << 8);
- index++;
- }
- if (io_len == 4) {
- value32 |= (BX_SELECTED_CONTROLLER(channel).buffer[index] << 16);
- value32 |= (BX_SELECTED_CONTROLLER(channel).buffer[index+1] << 24);
- index += 2;
- }
- BX_SELECTED_CONTROLLER(channel).buffer_index = index;
-
- if (BX_SELECTED_CONTROLLER(channel).buffer_index >= 512) {
- BX_SELECTED_CONTROLLER(channel).status.drq = 0;
- if (bx_dbg.disk || (BX_SELECTED_IS_CD(channel) && bx_dbg.cdrom))
- BX_INFO(("Read all drive ID Bytes ..."));
- }
- GOTO_RETURN_VALUE;
- }
- else
- BX_PANIC(("IO read(0x%04x): current command is %02xh", address,
- (unsigned) BX_SELECTED_CONTROLLER(channel).current_command));
-
- case 0xa0: {
- unsigned index = BX_SELECTED_CONTROLLER(channel).buffer_index;
- unsigned increment = 0;
-
- // Load block if necessary
- if (index >= 2048) {
- if (index > 2048)
- BX_PANIC(("index > 2048 : 0x%x",index));
- switch (BX_SELECTED_DRIVE(channel).atapi.command) {
- case 0x28: // read (10)
- case 0xa8: // read (12)
-#ifdef LOWLEVEL_CDROM
- if (!BX_SELECTED_DRIVE(channel).cdrom.ready) {
- BX_PANIC(("Read with CDROM not ready"));
- }
- BX_SELECTED_DRIVE(channel).cdrom.cd->read_block(BX_SELECTED_CONTROLLER(channel).buffer,
- BX_SELECTED_DRIVE(channel).cdrom.next_lba);
- BX_SELECTED_DRIVE(channel).cdrom.next_lba++;
- BX_SELECTED_DRIVE(channel).cdrom.remaining_blocks--;
-
- if (bx_dbg.disk || (BX_SELECTED_IS_CD(channel) && bx_dbg.cdrom))
- if (!BX_SELECTED_DRIVE(channel).cdrom.remaining_blocks)
- BX_INFO(("Last READ block loaded {CDROM}"));
- else
- BX_INFO(("READ block loaded (%d remaining) {CDROM}",
- BX_SELECTED_DRIVE(channel).cdrom.remaining_blocks));
-
- // one block transfered, start at beginning
- index = 0;
-#else
- BX_PANIC(("Read with no LOWLEVEL_CDROM"));
-#endif
- break;
-
- default: // no need to load a new block
- break;
- }
- }
-
- value32 = BX_SELECTED_CONTROLLER(channel).buffer[index+increment];
- increment++;
- if (io_len >= 2) {
- value32 |= (BX_SELECTED_CONTROLLER(channel).buffer[index+increment] << 8);
- increment++;
- }
- if (io_len == 4) {
- value32 |= (BX_SELECTED_CONTROLLER(channel).buffer[index+increment] << 16);
- value32 |= (BX_SELECTED_CONTROLLER(channel).buffer[index+increment+1] << 24);
- increment += 2;
- }
- BX_SELECTED_CONTROLLER(channel).buffer_index = index + increment;
- BX_SELECTED_CONTROLLER(channel).drq_index += increment;
-
- if (BX_SELECTED_CONTROLLER(channel).drq_index >= (unsigned)BX_SELECTED_DRIVE(channel).atapi.drq_bytes) {
- BX_SELECTED_CONTROLLER(channel).status.drq = 0;
- BX_SELECTED_CONTROLLER(channel).drq_index = 0;
-
- BX_SELECTED_DRIVE(channel).atapi.total_bytes_remaining -= BX_SELECTED_DRIVE(channel).atapi.drq_bytes;
-
- if (BX_SELECTED_DRIVE(channel).atapi.total_bytes_remaining > 0) {
- // one or more blocks remaining (works only for single block commands)
- if (bx_dbg.disk || (BX_SELECTED_IS_CD(channel) && bx_dbg.cdrom))
- BX_INFO(("PACKET drq bytes read"));
- BX_SELECTED_CONTROLLER(channel).interrupt_reason.i_o = 1;
- BX_SELECTED_CONTROLLER(channel).status.busy = 0;
- BX_SELECTED_CONTROLLER(channel).status.drq = 1;
- BX_SELECTED_CONTROLLER(channel).interrupt_reason.c_d = 0;
-
- // set new byte count if last block
- if (BX_SELECTED_DRIVE(channel).atapi.total_bytes_remaining < BX_SELECTED_CONTROLLER(channel).byte_count) {
- BX_SELECTED_CONTROLLER(channel).byte_count = BX_SELECTED_DRIVE(channel).atapi.total_bytes_remaining;
- }
- BX_SELECTED_DRIVE(channel).atapi.drq_bytes = BX_SELECTED_CONTROLLER(channel).byte_count;
-
- raise_interrupt(channel);
- } else {
- // all bytes read
- if (bx_dbg.disk || (BX_SELECTED_IS_CD(channel) && bx_dbg.cdrom))
- BX_INFO(("PACKET all bytes read"));
- BX_SELECTED_CONTROLLER(channel).interrupt_reason.i_o = 1;
- BX_SELECTED_CONTROLLER(channel).interrupt_reason.c_d = 1;
- BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1;
- BX_SELECTED_CONTROLLER(channel).interrupt_reason.rel = 0;
- BX_SELECTED_CONTROLLER(channel).status.busy = 0;
- BX_SELECTED_CONTROLLER(channel).status.drq = 0;
- BX_SELECTED_CONTROLLER(channel).status.err = 0;
-
- raise_interrupt(channel);
- }
- }
- GOTO_RETURN_VALUE;
- break;
- }
-
- // List all the read operations that are defined in the ATA/ATAPI spec
- // that we don't support. Commands that are listed here will cause a
- // BX_ERROR, which is non-fatal, and the command will be aborted.
- case 0x08: BX_ERROR(("read cmd 0x08 (DEVICE RESET) not supported")); command_aborted(channel, 0x08); break;
- case 0x10: BX_ERROR(("read cmd 0x10 (RECALIBRATE) not supported")); command_aborted(channel, 0x10); break;
- case 0x22: BX_ERROR(("read cmd 0x22 (READ LONG) not supported")); command_aborted(channel, 0x22); break;
- case 0x23: BX_ERROR(("read cmd 0x23 (READ LONG NO RETRY) not supported")); command_aborted(channel, 0x23); break;
- case 0x24: BX_ERROR(("read cmd 0x24 (READ SECTORS EXT) not supported")); command_aborted(channel, 0x24); break;
- case 0x25: BX_ERROR(("read cmd 0x25 (READ DMA EXT) not supported")); command_aborted(channel, 0x25); break;
- case 0x26: BX_ERROR(("read cmd 0x26 (READ DMA QUEUED EXT) not supported")); command_aborted(channel, 0x26); break;
- case 0x27: BX_ERROR(("read cmd 0x27 (READ NATIVE MAX ADDRESS EXT) not supported")); command_aborted(channel, 0x27); break;
- case 0x29: BX_ERROR(("read cmd 0x29 (READ MULTIPLE EXT) not supported")); command_aborted(channel, 0x29); break;
- case 0x2A: BX_ERROR(("read cmd 0x2A (READ STREAM DMA) not supported")); command_aborted(channel, 0x2A); break;
- case 0x2B: BX_ERROR(("read cmd 0x2B (READ STREAM PIO) not supported")); command_aborted(channel, 0x2B); break;
- case 0x2F: BX_ERROR(("read cmd 0x2F (READ LOG EXT) not supported")); command_aborted(channel, 0x2F); break;
- case 0x30: BX_ERROR(("read cmd 0x30 (WRITE SECTORS) not supported")); command_aborted(channel, 0x30); break;
- case 0x31: BX_ERROR(("read cmd 0x31 (WRITE SECTORS NO RETRY) not supported")); command_aborted(channel, 0x31); break;
- case 0x32: BX_ERROR(("read cmd 0x32 (WRITE LONG) not supported")); command_aborted(channel, 0x32); break;
- case 0x33: BX_ERROR(("read cmd 0x33 (WRITE LONG NO RETRY) not supported")); command_aborted(channel, 0x33); break;
- case 0x34: BX_ERROR(("read cmd 0x34 (WRITE SECTORS EXT) not supported")); command_aborted(channel, 0x34); break;
- case 0x35: BX_ERROR(("read cmd 0x35 (WRITE DMA EXT) not supported")); command_aborted(channel, 0x35); break;
- case 0x36: BX_ERROR(("read cmd 0x36 (WRITE DMA QUEUED EXT) not supported")); command_aborted(channel, 0x36); break;
- case 0x37: BX_ERROR(("read cmd 0x37 (SET MAX ADDRESS EXT) not supported")); command_aborted(channel, 0x37); break;
- case 0x38: BX_ERROR(("read cmd 0x38 (CFA WRITE SECTORS W/OUT ERASE) not supported")); command_aborted(channel, 0x38); break;
- case 0x39: BX_ERROR(("read cmd 0x39 (WRITE MULTIPLE EXT) not supported")); command_aborted(channel, 0x39); break;
- case 0x3A: BX_ERROR(("read cmd 0x3A (WRITE STREAM DMA) not supported")); command_aborted(channel, 0x3A); break;
- case 0x3B: BX_ERROR(("read cmd 0x3B (WRITE STREAM PIO) not supported")); command_aborted(channel, 0x3B); break;
- case 0x3F: BX_ERROR(("read cmd 0x3F (WRITE LOG EXT) not supported")); command_aborted(channel, 0x3F); break;
- case 0x40: BX_ERROR(("read cmd 0x40 (READ VERIFY SECTORS) not supported")); command_aborted(channel, 0x40); break;
- case 0x41: BX_ERROR(("read cmd 0x41 (READ VERIFY SECTORS NO RETRY) not supported")); command_aborted(channel, 0x41); break;
- case 0x42: BX_ERROR(("read cmd 0x42 (READ VERIFY SECTORS EXT) not supported")); command_aborted(channel, 0x42); break;
- case 0x50: BX_ERROR(("read cmd 0x50 (FORMAT TRACK) not supported")); command_aborted(channel, 0x50); break;
- case 0x51: BX_ERROR(("read cmd 0x51 (CONFIGURE STREAM) not supported")); command_aborted(channel, 0x51); break;
- case 0x70: BX_ERROR(("read cmd 0x70 (SEEK) not supported")); command_aborted(channel, 0x70); break;
- case 0x87: BX_ERROR(("read cmd 0x87 (CFA TRANSLATE SECTOR) not supported")); command_aborted(channel, 0x87); break;
- case 0x90: BX_ERROR(("read cmd 0x90 (EXECUTE DEVICE DIAGNOSTIC) not supported")); command_aborted(channel, 0x90); break;
- case 0x91: BX_ERROR(("read cmd 0x91 (INITIALIZE DEVICE PARAMETERS) not supported")); command_aborted(channel, 0x91); break;
- case 0x92: BX_ERROR(("read cmd 0x92 (DOWNLOAD MICROCODE) not supported")); command_aborted(channel, 0x92); break;
- case 0x94: BX_ERROR(("read cmd 0x94 (STANDBY IMMEDIATE) not supported")); command_aborted(channel, 0x94); break;
- case 0x95: BX_ERROR(("read cmd 0x95 (IDLE IMMEDIATE) not supported")); command_aborted(channel, 0x95); break;
- case 0x96: BX_ERROR(("read cmd 0x96 (STANDBY) not supported")); command_aborted(channel, 0x96); break;
- case 0x97: BX_ERROR(("read cmd 0x97 (IDLE) not supported")); command_aborted(channel, 0x97); break;
- case 0x98: BX_ERROR(("read cmd 0x98 (CHECK POWER MODE) not supported")); command_aborted(channel, 0x98); break;
- case 0x99: BX_ERROR(("read cmd 0x99 (SLEEP) not supported")); command_aborted(channel, 0x99); break;
- case 0xA2: BX_ERROR(("read cmd 0xA2 (SERVICE) not supported")); command_aborted(channel, 0xA2); break;
- case 0xB0: BX_ERROR(("read cmd 0xB0 (SMART DISABLE OPERATIONS) not supported")); command_aborted(channel, 0xB0); break;
- case 0xB1: BX_ERROR(("read cmd 0xB1 (DEVICE CONFIGURATION FREEZE LOCK) not supported")); command_aborted(channel, 0xB1); break;
- case 0xC0: BX_ERROR(("read cmd 0xC0 (CFA ERASE SECTORS) not supported")); command_aborted(channel, 0xC0); break;
- case 0xC4: BX_ERROR(("read cmd 0xC4 (READ MULTIPLE) not supported")); command_aborted(channel, 0xC4); break;
- case 0xC5: BX_ERROR(("read cmd 0xC5 (WRITE MULTIPLE) not supported")); command_aborted(channel, 0xC5); break;
- case 0xC6: BX_ERROR(("read cmd 0xC6 (SET MULTIPLE MODE) not supported")); command_aborted(channel, 0xC6); break;
- case 0xC7: BX_ERROR(("read cmd 0xC7 (READ DMA QUEUED) not supported")); command_aborted(channel, 0xC7); break;
- case 0xC8: BX_ERROR(("read cmd 0xC8 (READ DMA) not supported")); command_aborted(channel, 0xC8); break;
- case 0xC9: BX_ERROR(("read cmd 0xC9 (READ DMA NO RETRY) not supported")); command_aborted(channel, 0xC9); break;
- case 0xCA: BX_ERROR(("read cmd 0xCA (WRITE DMA) not supported")); command_aborted(channel, 0xCA); break;
- case 0xCC: BX_ERROR(("read cmd 0xCC (WRITE DMA QUEUED) not supported")); command_aborted(channel, 0xCC); break;
- case 0xCD: BX_ERROR(("read cmd 0xCD (CFA WRITE MULTIPLE W/OUT ERASE) not supported")); command_aborted(channel, 0xCD); break;
- case 0xD1: BX_ERROR(("read cmd 0xD1 (CHECK MEDIA CARD TYPE) not supported")); command_aborted(channel, 0xD1); break;
- case 0xDA: BX_ERROR(("read cmd 0xDA (GET MEDIA STATUS) not supported")); command_aborted(channel, 0xDA); break;
- case 0xDE: BX_ERROR(("read cmd 0xDE (MEDIA LOCK) not supported")); command_aborted(channel, 0xDE); break;
- case 0xDF: BX_ERROR(("read cmd 0xDF (MEDIA UNLOCK) not supported")); command_aborted(channel, 0xDF); break;
- case 0xE0: BX_ERROR(("read cmd 0xE0 (STANDBY IMMEDIATE) not supported")); command_aborted(channel, 0xE0); break;
- case 0xE1: BX_ERROR(("read cmd 0xE1 (IDLE IMMEDIATE) not supported")); command_aborted(channel, 0xE1); break;
- case 0xE2: BX_ERROR(("read cmd 0xE2 (STANDBY) not supported")); command_aborted(channel, 0xE2); break;
- case 0xE3: BX_ERROR(("read cmd 0xE3 (IDLE) not supported")); command_aborted(channel, 0xE3); break;
- case 0xE4: BX_ERROR(("read cmd 0xE4 (READ BUFFER) not supported")); command_aborted(channel, 0xE4); break;
- case 0xE5: BX_ERROR(("read cmd 0xE5 (CHECK POWER MODE) not supported")); command_aborted(channel, 0xE5); break;
- case 0xE6: BX_ERROR(("read cmd 0xE6 (SLEEP) not supported")); command_aborted(channel, 0xE6); break;
- case 0xE7: BX_ERROR(("read cmd 0xE7 (FLUSH CACHE) not supported")); command_aborted(channel, 0xE7); break;
- case 0xE8: BX_ERROR(("read cmd 0xE8 (WRITE BUFFER) not supported")); command_aborted(channel, 0xE8); break;
- case 0xEA: BX_ERROR(("read cmd 0xEA (FLUSH CACHE EXT) not supported")); command_aborted(channel, 0xEA); break;
- case 0xED: BX_ERROR(("read cmd 0xED (MEDIA EJECT) not supported")); command_aborted(channel, 0xED); break;
- case 0xEF: BX_ERROR(("read cmd 0xEF (SET FEATURES) not supported")); command_aborted(channel, 0xEF); break;
- case 0xF1: BX_ERROR(("read cmd 0xF1 (SECURITY SET PASSWORD) not supported")); command_aborted(channel, 0xF1); break;
- case 0xF2: BX_ERROR(("read cmd 0xF2 (SECURITY UNLOCK) not supported")); command_aborted(channel, 0xF2); break;
- case 0xF3: BX_ERROR(("read cmd 0xF3 (SECURITY ERASE PREPARE) not supported")); command_aborted(channel, 0xF3); break;
- case 0xF4: BX_ERROR(("read cmd 0xF4 (SECURITY ERASE UNIT) not supported")); command_aborted(channel, 0xF4); break;
- case 0xF5: BX_ERROR(("read cmd 0xF5 (SECURITY FREEZE LOCK) not supported")); command_aborted(channel, 0xF5); break;
- case 0xF6: BX_ERROR(("read cmd 0xF6 (SECURITY DISABLE PASSWORD) not supported")); command_aborted(channel, 0xF6); break;
- case 0xF8: BX_ERROR(("read cmd 0xF8 (READ NATIVE MAX ADDRESS) not supported")); command_aborted(channel, 0xF8); break;
- case 0xF9: BX_ERROR(("read cmd 0xF9 (SET MAX ADDRESS) not supported")); command_aborted(channel, 0xF9); break;
-
- default:
- BX_PANIC(("IO read(0x%04x): current command is %02xh", address,
- (unsigned) BX_SELECTED_CONTROLLER(channel).current_command));
- }
- break;
-
- case 0x01: // hard disk error register 0x1f1
- BX_SELECTED_CONTROLLER(channel).status.err = 0;
- value8 = (!BX_SELECTED_IS_PRESENT(channel)) ? 0 : BX_SELECTED_CONTROLLER(channel).error_register;
- goto return_value8;
- break;
- case 0x02: // hard disk sector count / interrupt reason 0x1f2
- value8 = (!BX_SELECTED_IS_PRESENT(channel)) ? 0 : BX_SELECTED_CONTROLLER(channel).sector_count;
- goto return_value8;
- break;
- case 0x03: // sector number 0x1f3
- value8 = (!BX_SELECTED_IS_PRESENT(channel)) ? 0 : BX_SELECTED_CONTROLLER(channel).sector_no;
- goto return_value8;
- case 0x04: // cylinder low 0x1f4
- // -- WARNING : On real hardware the controller registers are shared between drives.
- // So we must respond even if the select device is not present. Some OS uses this fact
- // to detect the disks.... minix2 for example
- value8 = (!BX_ANY_IS_PRESENT(channel)) ? 0 : (BX_SELECTED_CONTROLLER(channel).cylinder_no & 0x00ff);
- goto return_value8;
- case 0x05: // cylinder high 0x1f5
- // -- WARNING : On real hardware the controller registers are shared between drives.
- // So we must respond even if the select device is not present. Some OS uses this fact
- // to detect the disks.... minix2 for example
- value8 = (!BX_ANY_IS_PRESENT(channel)) ? 0 : BX_SELECTED_CONTROLLER(channel).cylinder_no >> 8;
- goto return_value8;
-
- case 0x06: // hard disk drive and head register 0x1f6
- // b7 Extended data field for ECC
- // b6/b5: Used to be sector size. 00=256,01=512,10=1024,11=128
- // Since 512 was always used, bit 6 was taken to mean LBA mode:
- // b6 1=LBA mode, 0=CHS mode
- // b5 1
- // b4: DRV
- // b3..0 HD3..HD0
- value8 = (1 << 7) |
- ((BX_SELECTED_CONTROLLER(channel).lba_mode>0) << 6) |
- (1 << 5) | // 01b = 512 sector size
- (BX_HD_THIS channels[channel].drive_select << 4) |
- (BX_SELECTED_CONTROLLER(channel).head_no << 0);
- goto return_value8;
- break;
-//BX_CONTROLLER(channel,0).lba_mode
-
- case 0x07: // Hard Disk Status 0x1f7
- case 0x16: // Hard Disk Alternate Status 0x3f6
- if (!BX_ANY_IS_PRESENT(channel)) {
- // (mch) Just return zero for these registers
- value8 = 0;
- } else {
- value8 = (
- (BX_SELECTED_CONTROLLER(channel).status.busy << 7) |
- (BX_SELECTED_CONTROLLER(channel).status.drive_ready << 6) |
- (BX_SELECTED_CONTROLLER(channel).status.write_fault << 5) |
- (BX_SELECTED_CONTROLLER(channel).status.seek_complete << 4) |
- (BX_SELECTED_CONTROLLER(channel).status.drq << 3) |
- (BX_SELECTED_CONTROLLER(channel).status.corrected_data << 2) |
- (BX_SELECTED_CONTROLLER(channel).status.index_pulse << 1) |
- (BX_SELECTED_CONTROLLER(channel).status.err) );
- BX_SELECTED_CONTROLLER(channel).status.index_pulse_count++;
- BX_SELECTED_CONTROLLER(channel).status.index_pulse = 0;
- if (BX_SELECTED_CONTROLLER(channel).status.index_pulse_count >= INDEX_PULSE_CYCLE) {
- BX_SELECTED_CONTROLLER(channel).status.index_pulse = 1;
- BX_SELECTED_CONTROLLER(channel).status.index_pulse_count = 0;
- }
- }
- if (port == 0x07) {
- DEV_pic_lower_irq(BX_HD_THIS channels[channel].irq);
- }
- goto return_value8;
- break;
-
- case 0x17: // Hard Disk Address Register 0x3f7
- // Obsolete and unsupported register. Not driven by hard
- // disk controller. Report all 1's. If floppy controller
- // is handling this address, it will call this function
- // set/clear D7 (the only bit it handles), then return
- // the combined value
- value8 = 0xff;
- goto return_value8;
- break;
-
- default:
- BX_PANIC(("hard drive: io read to address %x unsupported",
- (unsigned) address));
- }
-
- BX_PANIC(("hard drive: shouldnt get here!"));
- return(0);
-
- return_value32:
- BX_DEBUG(("32-bit read from %04x = %08x {%s}",
- (unsigned) address, value32, BX_SELECTED_TYPE_STRING(channel)));
- return value32;
-
- return_value16:
- BX_DEBUG(("16-bit read from %04x = %04x {%s}",
- (unsigned) address, value16, BX_SELECTED_TYPE_STRING(channel)));
- return value16;
-
- return_value8:
- BX_DEBUG(("8-bit read from %04x = %02x {%s}",
- (unsigned) address, value8, BX_SELECTED_TYPE_STRING(channel)));
- return value8;
-}
-
-
- // static IO port write callback handler
- // redirects to non-static class handler to avoid virtual functions
-
- void
-bx_hard_drive_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len)
-{
-#if !BX_USE_HD_SMF
- bx_hard_drive_c *class_ptr = (bx_hard_drive_c *) this_ptr;
-
- class_ptr->write(address, value, io_len);
-}
-
- void
-bx_hard_drive_c::write(Bit32u address, Bit32u value, unsigned io_len)
-{
-#else
- UNUSED(this_ptr);
-#endif // !BX_USE_HD_SMF
- off_t logical_sector;
- off_t ret;
- bx_bool prev_control_reset;
-
- Bit8u channel = BX_MAX_ATA_CHANNEL;
- Bit32u port = 0xff; // undefined
-
- for (channel=0; channel<BX_MAX_ATA_CHANNEL; channel++) {
- if ((address & 0xfff8) == BX_HD_THIS channels[channel].ioaddr1) {
- port = address - BX_HD_THIS channels[channel].ioaddr1;
- break;
- }
- else if ((address & 0xfff8) == BX_HD_THIS channels[channel].ioaddr2) {
- port = address - BX_HD_THIS channels[channel].ioaddr2 + 0x10;
- break;
- }
- }
-
- if (channel == BX_MAX_ATA_CHANNEL) {
- if (address != 0x03f6) {
- BX_PANIC(("write: unable to find ATA channel, ioport=0x%04x", address));
- } else {
- channel = 0;
- port = address - 0x03e0;
- }
- }
-
-#if BX_PDC20230C_VLBIDE_SUPPORT
-// pdc20230c is only available for first ata channel
-if (channel == 0) {
- BX_HD_THIS pdc20230c.prog_count = 0;
-
- if (BX_HD_THIS pdc20230c.prog_mode != 0) {
- switch (port) {
- case 0x03:
- BX_HD_THIS pdc20230c.p1f3_value = value;
- return;
- break;
- case 0x04:
- BX_HD_THIS pdc20230c.p1f4_value = value;
- return;
- break;
- }
- }
-}
-#endif
-
- if (bx_dbg.disk || (BX_SELECTED_IS_CD(channel) && bx_dbg.cdrom)) {
- switch (io_len) {
- case 1:
- BX_INFO(("8-bit write to %04x = %02x {%s}",
- (unsigned) address, (unsigned) value, BX_SELECTED_TYPE_STRING(channel)));
- break;
-
- case 2:
- BX_INFO(("16-bit write to %04x = %04x {%s}",
- (unsigned) address, (unsigned) value, BX_SELECTED_TYPE_STRING(channel)));
- break;
-
- case 4:
- BX_INFO(("32-bit write to %04x = %08x {%s}",
- (unsigned) address, (unsigned) value, BX_SELECTED_TYPE_STRING(channel)));
- break;
-
- default:
- BX_INFO(("unknown-size write to %04x = %08x {%s}",
- (unsigned) address, (unsigned) value, BX_SELECTED_TYPE_STRING(channel)));
- break;
- }
- }
-
- BX_DEBUG(("IO write to %04x = %02x", (unsigned) address, (unsigned) value));
-
- switch (port) {
- case 0x00: // 0x1f0
- switch (BX_SELECTED_CONTROLLER(channel).current_command) {
- case 0x30: // WRITE SECTORS
- if (BX_SELECTED_CONTROLLER(channel).buffer_index >= 512)
- BX_PANIC(("IO write(0x%04x): buffer_index >= 512", address));
-
-#if BX_SupportRepeatSpeedups
- if (DEV_bulk_io_quantum_requested()) {
- unsigned transferLen, quantumsMax;
-
- quantumsMax =
- (512 - BX_SELECTED_CONTROLLER(channel).buffer_index) / io_len;
- if ( quantumsMax == 0)
- BX_PANIC(("IO write(0x%04x): not enough space for write", address));
- DEV_bulk_io_quantum_transferred() =
- DEV_bulk_io_quantum_requested();
- if (quantumsMax < DEV_bulk_io_quantum_transferred())
- DEV_bulk_io_quantum_transferred() = quantumsMax;
- transferLen = io_len * DEV_bulk_io_quantum_transferred();
- memcpy(
- &BX_SELECTED_CONTROLLER(channel).buffer[BX_SELECTED_CONTROLLER(channel).buffer_index],
- (Bit8u*) DEV_bulk_io_host_addr(),
- transferLen);
- DEV_bulk_io_host_addr() += transferLen;
- BX_SELECTED_CONTROLLER(channel).buffer_index += transferLen;
- }
- else
-#endif
- {
- switch(io_len){
- case 4:
- BX_SELECTED_CONTROLLER(channel).buffer[BX_SELECTED_CONTROLLER(channel).buffer_index+3] = (Bit8u)(value >> 24);
- BX_SELECTED_CONTROLLER(channel).buffer[BX_SELECTED_CONTROLLER(channel).buffer_index+2] = (Bit8u)(value >> 16);
- case 2:
- BX_SELECTED_CONTROLLER(channel).buffer[BX_SELECTED_CONTROLLER(channel).buffer_index+1] = (Bit8u)(value >> 8);
- BX_SELECTED_CONTROLLER(channel).buffer[BX_SELECTED_CONTROLLER(channel).buffer_index] = (Bit8u) value;
- }
- BX_SELECTED_CONTROLLER(channel).buffer_index += io_len;
- }
-
- /* if buffer completely writtten */
- if (BX_SELECTED_CONTROLLER(channel).buffer_index >= 512) {
- off_t logical_sector;
- off_t ret;
-
-#if TEST_WRITE_BEYOND_END==1
- BX_SELECTED_CONTROLLER(channel).cylinder_no += 100000;
-#endif
- if (!calculate_logical_address(channel, &logical_sector)) {
- BX_ERROR(("write reached invalid sector %lu, aborting", (unsigned long)logical_sector));
- command_aborted (channel, BX_SELECTED_CONTROLLER(channel).current_command);
- return;
- }
-#if TEST_WRITE_BEYOND_END==2
- logical_sector += 100000;
-#endif
- ret = BX_SELECTED_DRIVE(channel).hard_drive->lseek(logical_sector * 512, SEEK_SET);
- if (ret < 0) {
- BX_ERROR(("could not lseek() hard drive image file at byte %lu", (unsigned long)logical_sector * 512));
- command_aborted (channel, BX_SELECTED_CONTROLLER(channel).current_command);
- return;
- }
- ret = BX_SELECTED_DRIVE(channel).hard_drive->write((bx_ptr_t) BX_SELECTED_CONTROLLER(channel).buffer, 512);
- if (ret < 512) {
- BX_ERROR(("could not write() hard drive image file at byte %lu", (unsigned long)logical_sector*512));
- command_aborted (channel, BX_SELECTED_CONTROLLER(channel).current_command);
- return;
- }
-
- BX_SELECTED_CONTROLLER(channel).buffer_index = 0;
-
- /* update sector count, sector number, cylinder,
- * drive, head, status
- * if there are more sectors, read next one in...
- */
-
- increment_address(channel);
-
- /* When the write is complete, controller clears the DRQ bit and
- * sets the BSY bit.
- * If at least one more sector is to be written, controller sets DRQ bit,
- * clears BSY bit, and issues IRQ
- */
-
- if (BX_SELECTED_CONTROLLER(channel).sector_count!=0) {
- BX_SELECTED_CONTROLLER(channel).status.busy = 0;
- BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1;
- BX_SELECTED_CONTROLLER(channel).status.drq = 1;
- BX_SELECTED_CONTROLLER(channel).status.corrected_data = 0;
- BX_SELECTED_CONTROLLER(channel).status.err = 0;
- }
- else { /* no more sectors to write */
- BX_SELECTED_CONTROLLER(channel).status.busy = 0;
- BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1;
- BX_SELECTED_CONTROLLER(channel).status.drq = 0;
- BX_SELECTED_CONTROLLER(channel).status.err = 0;
- BX_SELECTED_CONTROLLER(channel).status.corrected_data = 0;
- }
- raise_interrupt(channel);
- }
- break;
-
- case 0xa0: // PACKET
- if (BX_SELECTED_CONTROLLER(channel).buffer_index >= PACKET_SIZE)
- BX_PANIC(("IO write(0x%04x): buffer_index >= PACKET_SIZE", address));
- BX_SELECTED_CONTROLLER(channel).buffer[BX_SELECTED_CONTROLLER(channel).buffer_index] = value;
- BX_SELECTED_CONTROLLER(channel).buffer[BX_SELECTED_CONTROLLER(channel).buffer_index+1] = (value >> 8);
- BX_SELECTED_CONTROLLER(channel).buffer_index += 2;
-
- /* if packet completely writtten */
- if (BX_SELECTED_CONTROLLER(channel).buffer_index >= PACKET_SIZE) {
- // complete command received
- Bit8u atapi_command = BX_SELECTED_CONTROLLER(channel).buffer[0];
-
- if (bx_dbg.cdrom)
- BX_INFO(("cdrom: ATAPI command 0x%x started", atapi_command));
-
- switch (atapi_command) {
- case 0x00: // test unit ready
- if (BX_SELECTED_DRIVE(channel).cdrom.ready) {
- atapi_cmd_nop(channel);
- } else {
- atapi_cmd_error(channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
- }
- raise_interrupt(channel);
- break;
-
- case 0x03: { // request sense
- int alloc_length = BX_SELECTED_CONTROLLER(channel).buffer[4];
- init_send_atapi_command(channel, atapi_command, 18, alloc_length);
-
- // sense data
- BX_SELECTED_CONTROLLER(channel).buffer[0] = 0x70 | (1 << 7);
- BX_SELECTED_CONTROLLER(channel).buffer[1] = 0;
- BX_SELECTED_CONTROLLER(channel).buffer[2] = BX_SELECTED_DRIVE(channel).sense.sense_key;
- BX_SELECTED_CONTROLLER(channel).buffer[3] = BX_SELECTED_DRIVE(channel).sense.information.arr[0];
- BX_SELECTED_CONTROLLER(channel).buffer[4] = BX_SELECTED_DRIVE(channel).sense.information.arr[1];
- BX_SELECTED_CONTROLLER(channel).buffer[5] = BX_SELECTED_DRIVE(channel).sense.information.arr[2];
- BX_SELECTED_CONTROLLER(channel).buffer[6] = BX_SELECTED_DRIVE(channel).sense.information.arr[3];
- BX_SELECTED_CONTROLLER(channel).buffer[7] = 17-7;
- BX_SELECTED_CONTROLLER(channel).buffer[8] = BX_SELECTED_DRIVE(channel).sense.specific_inf.arr[0];
- BX_SELECTED_CONTROLLER(channel).buffer[9] = BX_SELECTED_DRIVE(channel).sense.specific_inf.arr[1];
- BX_SELECTED_CONTROLLER(channel).buffer[10] = BX_SELECTED_DRIVE(channel).sense.specific_inf.arr[2];
- BX_SELECTED_CONTROLLER(channel).buffer[11] = BX_SELECTED_DRIVE(channel).sense.specific_inf.arr[3];
- BX_SELECTED_CONTROLLER(channel).buffer[12] = BX_SELECTED_DRIVE(channel).sense.asc;
- BX_SELECTED_CONTROLLER(channel).buffer[13] = BX_SELECTED_DRIVE(channel).sense.ascq;
- BX_SELECTED_CONTROLLER(channel).buffer[14] = BX_SELECTED_DRIVE(channel).sense.fruc;
- BX_SELECTED_CONTROLLER(channel).buffer[15] = BX_SELECTED_DRIVE(channel).sense.key_spec.arr[0];
- BX_SELECTED_CONTROLLER(channel).buffer[16] = BX_SELECTED_DRIVE(channel).sense.key_spec.arr[1];
- BX_SELECTED_CONTROLLER(channel).buffer[17] = BX_SELECTED_DRIVE(channel).sense.key_spec.arr[2];
-
- ready_to_send_atapi(channel);
- }
- break;
-
- case 0x1b: { // start stop unit
- //bx_bool Immed = (BX_SELECTED_CONTROLLER(channel).buffer[1] >> 0) & 1;
- bx_bool LoEj = (BX_SELECTED_CONTROLLER(channel).buffer[4] >> 1) & 1;
- bx_bool Start = (BX_SELECTED_CONTROLLER(channel).buffer[4] >> 0) & 1;
-
- if (!LoEj && !Start) { // stop the disc
- BX_ERROR(("FIXME: Stop disc not implemented"));
- atapi_cmd_nop(channel);
- raise_interrupt(channel);
- } else if (!LoEj && Start) { // start (spin up) the disc
-#ifdef LOWLEVEL_CDROM
- BX_SELECTED_DRIVE(channel).cdrom.cd->start_cdrom();
-#endif
- BX_ERROR(("FIXME: ATAPI start disc not reading TOC"));
- atapi_cmd_nop(channel);
- raise_interrupt(channel);
- } else if (LoEj && !Start) { // Eject the disc
- atapi_cmd_nop(channel);
-
- if (BX_SELECTED_DRIVE(channel).cdrom.ready) {
-#ifdef LOWLEVEL_CDROM
- BX_SELECTED_DRIVE(channel).cdrom.cd->eject_cdrom();
-#endif
- BX_SELECTED_DRIVE(channel).cdrom.ready = 0;
- bx_options.atadevice[channel][BX_SLAVE_SELECTED(channel)].Ostatus->set(BX_EJECTED);
- bx_gui->update_drive_status_buttons();
- }
- raise_interrupt(channel);
- } else { // Load the disc
- // My guess is that this command only closes the tray, that's a no-op for us
- atapi_cmd_nop(channel);
- raise_interrupt(channel);
- }
- }
- break;
-
- case 0xbd: { // mechanism status
- uint16 alloc_length = read_16bit(BX_SELECTED_CONTROLLER(channel).buffer + 8);
-
- if (alloc_length == 0)
- BX_PANIC(("Zero allocation length to MECHANISM STATUS not impl."));
-
- init_send_atapi_command(channel, atapi_command, 8, alloc_length);
-
- BX_SELECTED_CONTROLLER(channel).buffer[0] = 0; // reserved for non changers
- BX_SELECTED_CONTROLLER(channel).buffer[1] = 0; // reserved for non changers
-
- BX_SELECTED_CONTROLLER(channel).buffer[2] = 0; // Current LBA (TODO!)
- BX_SELECTED_CONTROLLER(channel).buffer[3] = 0; // Current LBA (TODO!)
- BX_SELECTED_CONTROLLER(channel).buffer[4] = 0; // Current LBA (TODO!)
-
- BX_SELECTED_CONTROLLER(channel).buffer[5] = 1; // one slot
-
- BX_SELECTED_CONTROLLER(channel).buffer[6] = 0; // slot table length
- BX_SELECTED_CONTROLLER(channel).buffer[7] = 0; // slot table length
-
- ready_to_send_atapi(channel);
- }
- break;
-
- case 0x5a: { // mode sense
- uint16 alloc_length = read_16bit(BX_SELECTED_CONTROLLER(channel).buffer + 7);
-
- Bit8u PC = BX_SELECTED_CONTROLLER(channel).buffer[2] >> 6;
- Bit8u PageCode = BX_SELECTED_CONTROLLER(channel).buffer[2] & 0x3f;
-
- switch (PC) {
- case 0x0: // current values
- switch (PageCode) {
- case 0x01: // error recovery
- init_send_atapi_command(channel, atapi_command, sizeof(error_recovery_t) + 8, alloc_length);
-
- init_mode_sense_single(channel, &BX_SELECTED_DRIVE(channel).cdrom.current.error_recovery,
- sizeof(error_recovery_t));
- ready_to_send_atapi(channel);
- break;
-
- case 0x2a: // CD-ROM capabilities & mech. status
- init_send_atapi_command(channel, atapi_command, 28, alloc_length);
- init_mode_sense_single(channel, &BX_SELECTED_CONTROLLER(channel).buffer[8], 28);
- BX_SELECTED_CONTROLLER(channel).buffer[8] = 0x2a;
- BX_SELECTED_CONTROLLER(channel).buffer[9] = 0x12;
- BX_SELECTED_CONTROLLER(channel).buffer[10] = 0x00;
- BX_SELECTED_CONTROLLER(channel).buffer[11] = 0x00;
- // Multisession, Mode 2 Form 2, Mode 2 Form 1
- BX_SELECTED_CONTROLLER(channel).buffer[12] = 0x70;
- BX_SELECTED_CONTROLLER(channel).buffer[13] = (3 << 5);
- BX_SELECTED_CONTROLLER(channel).buffer[14] = (unsigned char)
-(1 |
- (BX_SELECTED_DRIVE(channel).cdrom.locked ? (1 << 1) : 0) |
- (1 << 3) |
- (1 << 5));
- BX_SELECTED_CONTROLLER(channel).buffer[15] = 0x00;
- BX_SELECTED_CONTROLLER(channel).buffer[16] = (706 >> 8) & 0xff;
- BX_SELECTED_CONTROLLER(channel).buffer[17] = 706 & 0xff;
- BX_SELECTED_CONTROLLER(channel).buffer[18] = 0;
- BX_SELECTED_CONTROLLER(channel).buffer[19] = 2;
- BX_SELECTED_CONTROLLER(channel).buffer[20] = (512 >> 8) & 0xff;
- BX_SELECTED_CONTROLLER(channel).buffer[21] = 512 & 0xff;
- BX_SELECTED_CONTROLLER(channel).buffer[22] = (706 >> 8) & 0xff;
- BX_SELECTED_CONTROLLER(channel).buffer[23] = 706 & 0xff;
- BX_SELECTED_CONTROLLER(channel).buffer[24] = 0;
- BX_SELECTED_CONTROLLER(channel).buffer[25] = 0;
- BX_SELECTED_CONTROLLER(channel).buffer[26] = 0;
- BX_SELECTED_CONTROLLER(channel).buffer[27] = 0;
- ready_to_send_atapi(channel);
- break;
-
- case 0x0d: // CD-ROM
- case 0x0e: // CD-ROM audio control
- case 0x3f: // all
- BX_ERROR(("cdrom: MODE SENSE (curr), code=%x"
- " not implemented yet",
- PageCode));
- atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST,
- ASC_INV_FIELD_IN_CMD_PACKET);
- raise_interrupt(channel);
- break;
-
- default:
- // not implemeted by this device
- BX_INFO(("cdrom: MODE SENSE PC=%x, PageCode=%x,"
- " not implemented by device",
- PC, PageCode));
- atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST,
- ASC_INV_FIELD_IN_CMD_PACKET);
- raise_interrupt(channel);
- break;
- }
- break;
-
- case 0x1: // changeable values
- switch (PageCode) {
- case 0x01: // error recovery
- case 0x0d: // CD-ROM
- case 0x0e: // CD-ROM audio control
- case 0x2a: // CD-ROM capabilities & mech. status
- case 0x3f: // all
- BX_ERROR(("cdrom: MODE SENSE (chg), code=%x"
- " not implemented yet",
- PageCode));
- atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST,
- ASC_INV_FIELD_IN_CMD_PACKET);
- raise_interrupt(channel);
- break;
-
- default:
- // not implemeted by this device
- BX_INFO(("cdrom: MODE SENSE PC=%x, PageCode=%x,"
- " not implemented by device",
- PC, PageCode));
- atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST,
- ASC_INV_FIELD_IN_CMD_PACKET);
- raise_interrupt(channel);
- break;
- }
- break;
-
- case 0x2: // default values
- switch (PageCode) {
- case 0x01: // error recovery
- case 0x0d: // CD-ROM
- case 0x0e: // CD-ROM audio control
- case 0x2a: // CD-ROM capabilities & mech. status
- case 0x3f: // all
- BX_PANIC(("cdrom: MODE SENSE (dflt), code=%x",
- PageCode));
- break;
-
- default:
- // not implemeted by this device
- BX_INFO(("cdrom: MODE SENSE PC=%x, PageCode=%x,"
- " not implemented by device",
- PC, PageCode));
- atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST,
- ASC_INV_FIELD_IN_CMD_PACKET);
- raise_interrupt(channel);
- break;
- }
- break;
-
- case 0x3: // saved values not implemented
- atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_SAVING_PARAMETERS_NOT_SUPPORTED);
- raise_interrupt(channel);
- break;
-
- default:
- BX_PANIC(("Should not get here!"));
- break;
- }
- }
- break;
-
- case 0x12: { // inquiry
- uint8 alloc_length = BX_SELECTED_CONTROLLER(channel).buffer[4];
-
- init_send_atapi_command(channel, atapi_command, 36, alloc_length);
-
- BX_SELECTED_CONTROLLER(channel).buffer[0] = 0x05; // CD-ROM
- BX_SELECTED_CONTROLLER(channel).buffer[1] = 0x80; // Removable
- BX_SELECTED_CONTROLLER(channel).buffer[2] = 0x00; // ISO, ECMA, ANSI version
- BX_SELECTED_CONTROLLER(channel).buffer[3] = 0x21; // ATAPI-2, as specified
- BX_SELECTED_CONTROLLER(channel).buffer[4] = 31; // additional length (total 36)
- BX_SELECTED_CONTROLLER(channel).buffer[5] = 0x00; // reserved
- BX_SELECTED_CONTROLLER(channel).buffer[6] = 0x00; // reserved
- BX_SELECTED_CONTROLLER(channel).buffer[7] = 0x00; // reserved
-
- // Vendor ID
- const char* vendor_id = "VTAB ";
- int i;
- for (i = 0; i < 8; i++)
- BX_SELECTED_CONTROLLER(channel).buffer[8+i] = vendor_id[i];
-
- // Product ID
- const char* product_id = "Turbo CD-ROM ";
- for (i = 0; i < 16; i++)
- BX_SELECTED_CONTROLLER(channel).buffer[16+i] = product_id[i];
-
- // Product Revision level
- const char* rev_level = "1.0 ";
- for (i = 0; i < 4; i++)
- BX_SELECTED_CONTROLLER(channel).buffer[32+i] = rev_level[i];
-
- ready_to_send_atapi(channel);
- }
- break;
-
- case 0x25: { // read cd-rom capacity
- // no allocation length???
- init_send_atapi_command(channel, atapi_command, 8, 8);
-
- if (BX_SELECTED_DRIVE(channel).cdrom.ready) {
- uint32 capacity = BX_SELECTED_DRIVE(channel).cdrom.capacity;
- BX_INFO(("Capacity is %d sectors (%d bytes)", capacity, capacity * 2048));
- BX_SELECTED_CONTROLLER(channel).buffer[0] = (capacity >> 24) & 0xff;
- BX_SELECTED_CONTROLLER(channel).buffer[1] = (capacity >> 16) & 0xff;
- BX_SELECTED_CONTROLLER(channel).buffer[2] = (capacity >> 8) & 0xff;
- BX_SELECTED_CONTROLLER(channel).buffer[3] = (capacity >> 0) & 0xff;
- BX_SELECTED_CONTROLLER(channel).buffer[4] = (2048 >> 24) & 0xff;
- BX_SELECTED_CONTROLLER(channel).buffer[5] = (2048 >> 16) & 0xff;
- BX_SELECTED_CONTROLLER(channel).buffer[6] = (2048 >> 8) & 0xff;
- BX_SELECTED_CONTROLLER(channel).buffer[7] = (2048 >> 0) & 0xff;
- ready_to_send_atapi(channel);
- } else {
- atapi_cmd_error(channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
- raise_interrupt(channel);
- }
- }
- break;
-
- case 0xbe: { // read cd
- if (BX_SELECTED_DRIVE(channel).cdrom.ready) {
- BX_ERROR(("Read CD with CD present not implemented"));
- atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET);
- raise_interrupt(channel);
- } else {
- atapi_cmd_error(channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
- raise_interrupt(channel);
- }
- }
- break;
-
- case 0x43: { // read toc
- if (BX_SELECTED_DRIVE(channel).cdrom.ready) {
-#ifdef LOWLEVEL_CDROM
- bool msf = (BX_SELECTED_CONTROLLER(channel).buffer[1] >> 1) & 1;
- uint8 starting_track = BX_SELECTED_CONTROLLER(channel).buffer[6];
-#endif
- uint16 alloc_length = read_16bit(BX_SELECTED_CONTROLLER(channel).buffer + 7);
-
- uint8 format = (BX_SELECTED_CONTROLLER(channel).buffer[9] >> 6);
- int i;
- switch (format) {
- case 0:
-#ifdef LOWLEVEL_CDROM
- int toc_length;
- if (!(BX_SELECTED_DRIVE(channel).cdrom.cd->read_toc(BX_SELECTED_CONTROLLER(channel).buffer,
- &toc_length, msf, starting_track))) {
- atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST,
- ASC_INV_FIELD_IN_CMD_PACKET);
- raise_interrupt(channel);
- } else {
- init_send_atapi_command(channel, atapi_command, toc_length, alloc_length);
- ready_to_send_atapi(channel);
- }
-#else
- BX_PANIC(("LOWLEVEL_CDROM not defined"));
-#endif
- break;
-
- case 1:
- // multi session stuff. we ignore this and emulate a single session only
- init_send_atapi_command(channel, atapi_command, 12, alloc_length);
-
- BX_SELECTED_CONTROLLER(channel).buffer[0] = 0;
- BX_SELECTED_CONTROLLER(channel).buffer[1] = 0x0a;
- BX_SELECTED_CONTROLLER(channel).buffer[2] = 1;
- BX_SELECTED_CONTROLLER(channel).buffer[3] = 1;
- for (i = 0; i < 8; i++)
- BX_SELECTED_CONTROLLER(channel).buffer[4+i] = 0;
-
- ready_to_send_atapi(channel);
- break;
-
- case 2:
- default:
- BX_PANIC(("(READ TOC) Format %d not supported", format));
- break;
- }
- } else {
- atapi_cmd_error(channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
- raise_interrupt(channel);
- }
- }
- break;
-
- case 0x28: // read (10)
- case 0xa8: // read (12)
- {
-
- uint32 transfer_length;
- if (atapi_command == 0x28)
- transfer_length = read_16bit(BX_SELECTED_CONTROLLER(channel).buffer + 7);
- else
- transfer_length = read_32bit(BX_SELECTED_CONTROLLER(channel).buffer + 6);
-
- uint32 lba = read_32bit(BX_SELECTED_CONTROLLER(channel).buffer + 2);
-
- if (!BX_SELECTED_DRIVE(channel).cdrom.ready) {
- atapi_cmd_error(channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
- raise_interrupt(channel);
- break;
- }
-
- if (transfer_length == 0) {
- atapi_cmd_nop(channel);
- raise_interrupt(channel);
- BX_INFO(("READ(%d) with transfer length 0, ok", atapi_command==0x28?10:12));
- break;
- }
-
- if (lba + transfer_length > BX_SELECTED_DRIVE(channel).cdrom.capacity) {
- atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_LOGICAL_BLOCK_OOR);
- raise_interrupt(channel);
- break;
- }
-
- BX_DEBUG(("cdrom: READ (%d) LBA=%d LEN=%d", atapi_command==0x28?10:12, lba, transfer_length));
-
- // handle command
- init_send_atapi_command(channel, atapi_command, transfer_length * 2048,
- transfer_length * 2048, true);
- BX_SELECTED_DRIVE(channel).cdrom.remaining_blocks = transfer_length;
- BX_SELECTED_DRIVE(channel).cdrom.next_lba = lba;
- ready_to_send_atapi(channel);
- }
- break;
-
- case 0x2b: { // seek
- uint32 lba = read_32bit(BX_SELECTED_CONTROLLER(channel).buffer + 2);
- if (!BX_SELECTED_DRIVE(channel).cdrom.ready) {
- atapi_cmd_error(channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
- raise_interrupt(channel);
- break;
- }
-
- if (lba > BX_SELECTED_DRIVE(channel).cdrom.capacity) {
- atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_LOGICAL_BLOCK_OOR);
- raise_interrupt(channel);
- break;
- }
- BX_INFO(("cdrom: SEEK (ignored)"));
- atapi_cmd_nop(channel);
- raise_interrupt(channel);
- }
- break;
-
- case 0x1e: { // prevent/allow medium removal
- if (BX_SELECTED_DRIVE(channel).cdrom.ready) {
- BX_SELECTED_DRIVE(channel).cdrom.locked = BX_SELECTED_CONTROLLER(channel).buffer[4] & 1;
- atapi_cmd_nop(channel);
- } else {
- atapi_cmd_error(channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
- }
- raise_interrupt(channel);
- }
- break;
-
- case 0x42: { // read sub-channel
- bool msf = get_packet_field(channel,1, 1, 1);
- bool sub_q = get_packet_field(channel,2, 6, 1);
- uint8 data_format = get_packet_byte(channel,3);
- uint8 track_number = get_packet_byte(channel,6);
- uint16 alloc_length = get_packet_word(channel,7);
- UNUSED(msf);
- UNUSED(data_format);
- UNUSED(track_number);
-
- if (!BX_SELECTED_DRIVE(channel).cdrom.ready) {
- atapi_cmd_error(channel, SENSE_NOT_READY, ASC_MEDIUM_NOT_PRESENT);
- raise_interrupt(channel);
- } else {
- BX_SELECTED_CONTROLLER(channel).buffer[0] = 0;
- BX_SELECTED_CONTROLLER(channel).buffer[1] = 0; // audio not supported
- BX_SELECTED_CONTROLLER(channel).buffer[2] = 0;
- BX_SELECTED_CONTROLLER(channel).buffer[3] = 0;
-
- int ret_len = 4; // header size
-
- if (sub_q) { // !sub_q == header only
- BX_ERROR(("Read sub-channel with SubQ not implemented"));
- atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST,
- ASC_INV_FIELD_IN_CMD_PACKET);
- raise_interrupt(channel);
- }
-
- init_send_atapi_command(channel, atapi_command, ret_len, alloc_length);
- ready_to_send_atapi(channel);
- }
- }
- break;
-
- case 0x51: { // read disc info
- // no-op to keep the Linux CD-ROM driver happy
- atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET);
- raise_interrupt(channel);
- }
- break;
-
- case 0x55: // mode select
- case 0xa6: // load/unload cd
- case 0x4b: // pause/resume
- case 0x45: // play audio
- case 0x47: // play audio msf
- case 0xbc: // play cd
- case 0xb9: // read cd msf
- case 0x44: // read header
- case 0xba: // scan
- case 0xbb: // set cd speed
- case 0x4e: // stop play/scan
- case 0x46: // ???
- case 0x4a: // ???
- BX_ERROR(("ATAPI command 0x%x not implemented yet",
- atapi_command));
- atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET);
- raise_interrupt(channel);
- break;
- default:
- BX_PANIC(("Unknown ATAPI command 0x%x (%d)",
- atapi_command, atapi_command));
- // We'd better signal the error if the user chose to continue
- atapi_cmd_error(channel, SENSE_ILLEGAL_REQUEST, ASC_INV_FIELD_IN_CMD_PACKET);
- raise_interrupt(channel);
- break;
- }
- }
-
- break;
-
- default:
- BX_PANIC(("IO write(0x%04x): current command is %02xh", address,
- (unsigned) BX_SELECTED_CONTROLLER(channel).current_command));
- }
- break;
-
- case 0x01: // hard disk write precompensation 0x1f1
- WRITE_FEATURES(channel,value);
- if (bx_dbg.disk || (BX_SELECTED_IS_CD(channel) && bx_dbg.cdrom)) {
- if (value == 0xff)
- BX_INFO(("no precompensation {%s}", BX_SELECTED_TYPE_STRING(channel)));
- else
- BX_INFO(("precompensation value %02x {%s}", (unsigned) value, BX_SELECTED_TYPE_STRING(channel)));
- }
- break;
-
- case 0x02: // hard disk sector count 0x1f2
- WRITE_SECTOR_COUNT(channel,value);
- if (bx_dbg.disk || (BX_SELECTED_IS_CD(channel) && bx_dbg.cdrom))
- BX_INFO(("sector count = %u {%s}", (unsigned) value, BX_SELECTED_TYPE_STRING(channel)));
- break;
-
- case 0x03: // hard disk sector number 0x1f3
- WRITE_SECTOR_NUMBER(channel,value);
- if (bx_dbg.disk || (BX_SELECTED_IS_CD(channel) && bx_dbg.cdrom))
- BX_INFO(("sector number = %u {%s}", (unsigned) value, BX_SELECTED_TYPE_STRING(channel)));
- break;
-
- case 0x04: // hard disk cylinder low 0x1f4
- WRITE_CYLINDER_LOW(channel,value);
- if (bx_dbg.disk || (BX_SELECTED_IS_CD(channel) && bx_dbg.cdrom))
- BX_INFO(("cylinder low = %02xh {%s}", (unsigned) value, BX_SELECTED_TYPE_STRING(channel)));
- break;
-
- case 0x05: // hard disk cylinder high 0x1f5
- WRITE_CYLINDER_HIGH(channel,value);
- if (bx_dbg.disk || (BX_SELECTED_IS_CD(channel) && bx_dbg.cdrom))
- BX_INFO(("cylinder high = %02xh {%s}", (unsigned) value, BX_SELECTED_TYPE_STRING(channel)));
- break;
-
- case 0x06: // hard disk drive and head register 0x1f6
- // b7 Extended data field for ECC
- // b6/b5: Used to be sector size. 00=256,01=512,10=1024,11=128
- // Since 512 was always used, bit 6 was taken to mean LBA mode:
- // b6 1=LBA mode, 0=CHS mode
- // b5 1
- // b4: DRV
- // b3..0 HD3..HD0
- {
- if ( (value & 0xa0) != 0xa0 ) // 1x1xxxxx
- BX_INFO(("IO write 0x%04x (%02x): not 1x1xxxxxb", address, (unsigned) value));
- Bit32u drvsel = BX_HD_THIS channels[channel].drive_select = (value >> 4) & 0x01;
- WRITE_HEAD_NO(channel,value & 0xf);
- if (BX_SELECTED_CONTROLLER(channel).lba_mode == 0 && ((value >> 6) & 1) == 1)
- BX_DEBUG(("enabling LBA mode"));
- WRITE_LBA_MODE(channel,(value >> 6) & 1);
- if (!BX_SELECTED_IS_PRESENT(channel)) {
- BX_ERROR (("device set to %d which does not exist",drvsel));
- BX_SELECTED_CONTROLLER(channel).error_register = 0x04; // aborted
- BX_SELECTED_CONTROLLER(channel).status.err = 1;
- }
- break;
- }
-
- case 0x07: // hard disk command 0x1f7
- // (mch) Writes to the command register with drive_select != 0
- // are ignored if no secondary device is present
- if ((BX_SLAVE_SELECTED(channel)) && (!BX_SLAVE_IS_PRESENT(channel)))
- break;
- // Writes to the command register clear the IRQ
- DEV_pic_lower_irq(BX_HD_THIS channels[channel].irq);
-
- if (BX_SELECTED_CONTROLLER(channel).status.busy)
- BX_PANIC(("hard disk: command sent, controller BUSY"));
- if ( (value & 0xf0) == 0x10 )
- value = 0x10;
- switch (value) {
-
- case 0x10: // CALIBRATE DRIVE
- if (!BX_SELECTED_IS_HD(channel))
- BX_PANIC(("calibrate drive issued to non-disk"));
- if (!BX_SELECTED_IS_PRESENT(channel)) {
- BX_SELECTED_CONTROLLER(channel).error_register = 0x02; // Track 0 not found
- BX_SELECTED_CONTROLLER(channel).status.busy = 0;
- BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1;
- BX_SELECTED_CONTROLLER(channel).status.seek_complete = 0;
- BX_SELECTED_CONTROLLER(channel).status.drq = 0;
- BX_SELECTED_CONTROLLER(channel).status.err = 1;
- raise_interrupt(channel);
- BX_INFO(("calibrate drive: disk ata%d-%d not present", channel, BX_SLAVE_SELECTED(channel)));
- break;
- }
-
- /* move head to cylinder 0, issue IRQ */
- BX_SELECTED_CONTROLLER(channel).error_register = 0;
- BX_SELECTED_CONTROLLER(channel).cylinder_no = 0;
- BX_SELECTED_CONTROLLER(channel).status.busy = 0;
- BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1;
- BX_SELECTED_CONTROLLER(channel).status.seek_complete = 1;
- BX_SELECTED_CONTROLLER(channel).status.drq = 0;
- BX_SELECTED_CONTROLLER(channel).status.err = 0;
- raise_interrupt(channel);
- break;
-
- case 0x20: // READ MULTIPLE SECTORS, with retries
- case 0x21: // READ MULTIPLE SECTORS, without retries
- /* update sector_no, always points to current sector
- * after each sector is read to buffer, DRQ bit set and issue IRQ
- * if interrupt handler transfers all data words into main memory,
- * and more sectors to read, then set BSY bit again, clear DRQ and
- * read next sector into buffer
- * sector count of 0 means 256 sectors
- */
-
- if (!BX_SELECTED_IS_HD(channel)) {
- BX_ERROR(("read multiple issued to non-disk"));
- command_aborted(channel, value);
- break;
- }
-
- BX_SELECTED_CONTROLLER(channel).current_command = value;
-
- // Lose98 accesses 0/0/0 in CHS mode
- if (!BX_SELECTED_CONTROLLER(channel).lba_mode &&
- !BX_SELECTED_CONTROLLER(channel).head_no &&
- !BX_SELECTED_CONTROLLER(channel).cylinder_no &&
- !BX_SELECTED_CONTROLLER(channel).sector_no) {
- BX_INFO(("Read from 0/0/0, aborting command"));
- command_aborted(channel, value);
- break;
- }
-
-#if TEST_READ_BEYOND_END==2
- BX_SELECTED_CONTROLLER(channel).cylinder_no += 100000;
-#endif
- if (!calculate_logical_address(channel, &logical_sector)) {
- BX_ERROR(("initial read from sector %lu out of bounds, aborting", (unsigned long)logical_sector));
- command_aborted(channel, value);
- break;
- }
-#if TEST_READ_BEYOND_END==3
- logical_sector += 100000;
-#endif
- ret=BX_SELECTED_DRIVE(channel).hard_drive->lseek(logical_sector * 512, SEEK_SET);
- if (ret < 0) {
- BX_ERROR (("could not lseek() hard drive image file, aborting"));
- command_aborted(channel, value);
- break;
- }
- ret = BX_SELECTED_DRIVE(channel).hard_drive->read((bx_ptr_t) BX_SELECTED_CONTROLLER(channel).buffer, 512);
- if (ret < 512) {
- BX_ERROR(("logical sector was %lu", (unsigned long)logical_sector));
- BX_ERROR(("could not read() hard drive image file at byte %lu", (unsigned long)logical_sector*512));
- command_aborted(channel, value);
- break;
- }
-
- BX_SELECTED_CONTROLLER(channel).error_register = 0;
- BX_SELECTED_CONTROLLER(channel).status.busy = 0;
- BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1;
- BX_SELECTED_CONTROLLER(channel).status.seek_complete = 1;
- BX_SELECTED_CONTROLLER(channel).status.drq = 1;
- BX_SELECTED_CONTROLLER(channel).status.corrected_data = 0;
- BX_SELECTED_CONTROLLER(channel).status.err = 0;
- BX_SELECTED_CONTROLLER(channel).buffer_index = 0;
- raise_interrupt(channel);
- break;
-
- case 0x30: /* WRITE SECTORS, with retries */
- /* update sector_no, always points to current sector
- * after each sector is read to buffer, DRQ bit set and issue IRQ
- * if interrupt handler transfers all data words into main memory,
- * and more sectors to read, then set BSY bit again, clear DRQ and
- * read next sector into buffer
- * sector count of 0 means 256 sectors
- */
-
- if (!BX_SELECTED_IS_HD(channel))
- BX_PANIC(("write multiple issued to non-disk"));
-
- if (BX_SELECTED_CONTROLLER(channel).status.busy) {
- BX_PANIC(("write command: BSY bit set"));
- }
- BX_SELECTED_CONTROLLER(channel).current_command = value;
-
- // implicit seek done :^)
- BX_SELECTED_CONTROLLER(channel).error_register = 0;
- BX_SELECTED_CONTROLLER(channel).status.busy = 0;
- // BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1;
- BX_SELECTED_CONTROLLER(channel).status.seek_complete = 1;
- BX_SELECTED_CONTROLLER(channel).status.drq = 1;
- BX_SELECTED_CONTROLLER(channel).status.err = 0;
- BX_SELECTED_CONTROLLER(channel).buffer_index = 0;
- break;
-
- case 0x90: // EXECUTE DEVICE DIAGNOSTIC
- if (BX_SELECTED_CONTROLLER(channel).status.busy) {
- BX_PANIC(("diagnostic command: BSY bit set"));
- }
- if (!BX_SELECTED_IS_HD(channel))
- BX_PANIC(("drive diagnostics issued to non-disk"));
- BX_SELECTED_CONTROLLER(channel).error_register = 0x81; // Drive 1 failed, no error on drive 0
- // BX_SELECTED_CONTROLLER(channel).status.busy = 0; // not needed
- BX_SELECTED_CONTROLLER(channel).status.drq = 0;
- BX_SELECTED_CONTROLLER(channel).status.err = 0;
- break;
-
- case 0x91: // INITIALIZE DRIVE PARAMETERS
- if (BX_SELECTED_CONTROLLER(channel).status.busy) {
- BX_PANIC(("init drive parameters command: BSY bit set"));
- }
- if (!BX_SELECTED_IS_HD(channel))
- BX_PANIC(("initialize drive parameters issued to non-disk"));
- // sets logical geometry of specified drive
- BX_DEBUG(("init drive params: sec=%u, drive sel=%u, head=%u",
- (unsigned) BX_SELECTED_CONTROLLER(channel).sector_count,
- (unsigned) BX_HD_THIS channels[channel].drive_select,
- (unsigned) BX_SELECTED_CONTROLLER(channel).head_no));
- if (!BX_SELECTED_IS_PRESENT(channel)) {
- BX_PANIC(("init drive params: disk ata%d-%d not present", channel, BX_SLAVE_SELECTED(channel)));
- //BX_SELECTED_CONTROLLER(channel).error_register = 0x12;
- BX_SELECTED_CONTROLLER(channel).status.busy = 0;
- BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1;
- BX_SELECTED_CONTROLLER(channel).status.drq = 0;
- BX_SELECTED_CONTROLLER(channel).status.err = 0;
- raise_interrupt(channel);
- break;
- }
- if (BX_SELECTED_CONTROLLER(channel).sector_count != BX_SELECTED_DRIVE(channel).hard_drive->sectors)
- BX_PANIC(("init drive params: sector count doesnt match %d!=%d", BX_SELECTED_CONTROLLER(channel).sector_count, BX_SELECTED_DRIVE(channel).hard_drive->sectors));
- if ( BX_SELECTED_CONTROLLER(channel).head_no != (BX_SELECTED_DRIVE(channel).hard_drive->heads-1) )
- BX_PANIC(("init drive params: head number doesn't match %d != %d",BX_SELECTED_CONTROLLER(channel).head_no, BX_SELECTED_DRIVE(channel).hard_drive->heads-1));
- BX_SELECTED_CONTROLLER(channel).status.busy = 0;
- BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1;
- BX_SELECTED_CONTROLLER(channel).status.drq = 0;
- BX_SELECTED_CONTROLLER(channel).status.err = 0;
- raise_interrupt(channel);
- break;
-
- case 0xec: // IDENTIFY DEVICE
- if (bx_options.OnewHardDriveSupport->get ()) {
- if (bx_dbg.disk || (BX_SELECTED_IS_CD(channel) && bx_dbg.cdrom))
- BX_INFO(("Drive ID Command issued : 0xec "));
-
- if (!BX_SELECTED_IS_PRESENT(channel)) {
- BX_INFO(("disk ata%d-%d not present, aborting",channel,BX_SLAVE_SELECTED(channel)));
- command_aborted(channel, value);
- break;
- }
- if (BX_SELECTED_IS_CD(channel)) {
- BX_SELECTED_CONTROLLER(channel).head_no = 0;
- BX_SELECTED_CONTROLLER(channel).sector_count = 1;
- BX_SELECTED_CONTROLLER(channel).sector_no = 1;
- BX_SELECTED_CONTROLLER(channel).cylinder_no = 0xeb14;
- command_aborted(channel, 0xec);
- } else {
- BX_SELECTED_CONTROLLER(channel).current_command = value;
- BX_SELECTED_CONTROLLER(channel).error_register = 0;
-
- // See ATA/ATAPI-4, 8.12
- BX_SELECTED_CONTROLLER(channel).status.busy = 0;
- BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1;
- BX_SELECTED_CONTROLLER(channel).status.write_fault = 0;
- BX_SELECTED_CONTROLLER(channel).status.drq = 1;
- BX_SELECTED_CONTROLLER(channel).status.err = 0;
-
- BX_SELECTED_CONTROLLER(channel).status.seek_complete = 1;
- BX_SELECTED_CONTROLLER(channel).status.corrected_data = 0;
-
- BX_SELECTED_CONTROLLER(channel).buffer_index = 0;
- raise_interrupt(channel);
- identify_drive(channel);
- }
- }
- else {
- BX_INFO(("sent IDENTIFY DEVICE (0xec) to old hard drive"));
- command_aborted(channel, value);
- }
- break;
-
- case 0xef: // SET FEATURES
- switch(BX_SELECTED_CONTROLLER(channel).features) {
- case 0x02: // Enable and
- case 0x82: // Disable write cache.
- case 0xAA: // Enable and
- case 0x55: // Disable look-ahead cache.
- case 0xCC: // Enable and
- case 0x66: // Disable reverting to power-on default
- BX_INFO(("SET FEATURES subcommand 0x%02x not supported by disk.", (unsigned) BX_SELECTED_CONTROLLER(channel).features));
- command_aborted(channel, value);
- break;
-
- default:
- BX_PANIC(("SET FEATURES with unknown subcommand: 0x%02x", (unsigned) BX_SELECTED_CONTROLLER(channel).features ));
- // We'd better signal the error if the user chose to continue
- command_aborted(channel, value);
- }
- break;
-
- case 0x40: // READ VERIFY SECTORS
- if (bx_options.OnewHardDriveSupport->get ()) {
- if (!BX_SELECTED_IS_HD(channel))
- BX_PANIC(("read verify issued to non-disk"));
- BX_INFO(("Verify Command : 0x40 ! "));
- BX_SELECTED_CONTROLLER(channel).status.busy = 0;
- BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1;
- BX_SELECTED_CONTROLLER(channel).status.drq = 0;
- BX_SELECTED_CONTROLLER(channel).status.err = 0;
- raise_interrupt(channel);
- }
- else {
- BX_INFO(("sent READ VERIFY SECTORS (0x40) to old hard drive"));
- command_aborted(channel, value);
- }
- break;
-
- case 0xc6: // SET MULTIPLE MODE (mch)
- if (BX_SELECTED_CONTROLLER(channel).sector_count != 128 &&
- BX_SELECTED_CONTROLLER(channel).sector_count != 64 &&
- BX_SELECTED_CONTROLLER(channel).sector_count != 32 &&
- BX_SELECTED_CONTROLLER(channel).sector_count != 16 &&
- BX_SELECTED_CONTROLLER(channel).sector_count != 8 &&
- BX_SELECTED_CONTROLLER(channel).sector_count != 4 &&
- BX_SELECTED_CONTROLLER(channel).sector_count != 2)
- command_aborted(channel, value);
-
- if (!BX_SELECTED_IS_HD(channel))
- BX_PANIC(("set multiple mode issued to non-disk"));
-
- BX_SELECTED_CONTROLLER(channel).sectors_per_block = BX_SELECTED_CONTROLLER(channel).sector_count;
- BX_SELECTED_CONTROLLER(channel).status.busy = 0;
- BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1;
- BX_SELECTED_CONTROLLER(channel).status.write_fault = 0;
- BX_SELECTED_CONTROLLER(channel).status.drq = 0;
- BX_SELECTED_CONTROLLER(channel).status.err = 0;
- break;
-
- // ATAPI commands
- case 0xa1: // IDENTIFY PACKET DEVICE
- if (BX_SELECTED_IS_CD(channel)) {
- BX_SELECTED_CONTROLLER(channel).current_command = value;
- BX_SELECTED_CONTROLLER(channel).error_register = 0;
-
- BX_SELECTED_CONTROLLER(channel).status.busy = 0;
- BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1;
- BX_SELECTED_CONTROLLER(channel).status.write_fault = 0;
- BX_SELECTED_CONTROLLER(channel).status.drq = 1;
- BX_SELECTED_CONTROLLER(channel).status.err = 0;
-
- BX_SELECTED_CONTROLLER(channel).status.seek_complete = 1;
- BX_SELECTED_CONTROLLER(channel).status.corrected_data = 0;
-
- BX_SELECTED_CONTROLLER(channel).buffer_index = 0;
- raise_interrupt(channel);
- identify_ATAPI_drive(channel);
- } else {
- command_aborted(channel, 0xa1);
- }
- break;
-
- case 0x08: // DEVICE RESET (atapi)
- if (BX_SELECTED_IS_CD(channel)) {
- BX_SELECTED_CONTROLLER(channel).status.busy = 1;
- BX_SELECTED_CONTROLLER(channel).error_register &= ~(1 << 7);
-
- // device signature
- BX_SELECTED_CONTROLLER(channel).head_no = 0;
- BX_SELECTED_CONTROLLER(channel).sector_count = 1;
- BX_SELECTED_CONTROLLER(channel).sector_no = 1;
- BX_SELECTED_CONTROLLER(channel).cylinder_no = 0xeb14;
-
- BX_SELECTED_CONTROLLER(channel).status.write_fault = 0;
- BX_SELECTED_CONTROLLER(channel).status.drq = 0;
- BX_SELECTED_CONTROLLER(channel).status.corrected_data = 0;
- BX_SELECTED_CONTROLLER(channel).status.err = 0;
-
- BX_SELECTED_CONTROLLER(channel).status.busy = 0;
-
- } else {
- BX_DEBUG(("ATAPI Device Reset on non-cd device"));
- command_aborted(channel, 0x08);
- }
- break;
-
- case 0xa0: // SEND PACKET (atapi)
- if (BX_SELECTED_IS_CD(channel)) {
- // PACKET
- if (BX_SELECTED_CONTROLLER(channel).features & (1 << 0))
- BX_PANIC(("PACKET-DMA not supported"));
- if (BX_SELECTED_CONTROLLER(channel).features & (1 << 1))
- BX_PANIC(("PACKET-overlapped not supported"));
-
- // We're already ready!
- BX_SELECTED_CONTROLLER(channel).sector_count = 1;
- BX_SELECTED_CONTROLLER(channel).status.busy = 0;
- BX_SELECTED_CONTROLLER(channel).status.write_fault = 0;
- // serv bit??
- BX_SELECTED_CONTROLLER(channel).status.drq = 1;
- BX_SELECTED_CONTROLLER(channel).status.err = 0;
-
- // NOTE: no interrupt here
- BX_SELECTED_CONTROLLER(channel).current_command = value;
- BX_SELECTED_CONTROLLER(channel).buffer_index = 0;
- } else {
- command_aborted (channel, 0xa0);
- }
- break;
-
- case 0xa2: // SERVICE (atapi), optional
- if (BX_SELECTED_IS_CD(channel)) {
- BX_PANIC(("ATAPI SERVICE not implemented"));
- } else {
- command_aborted (channel, 0xa2);
- }
- break;
-
- // power management
- case 0xe5: // CHECK POWER MODE
- BX_SELECTED_CONTROLLER(channel).status.busy = 0;
- BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1;
- BX_SELECTED_CONTROLLER(channel).status.write_fault = 0;
- BX_SELECTED_CONTROLLER(channel).status.drq = 0;
- BX_SELECTED_CONTROLLER(channel).status.err = 0;
- BX_SELECTED_CONTROLLER(channel).sector_count = 0xff; // Active or Idle mode
- raise_interrupt(channel);
- break;
-
- case 0x70: // SEEK (cgs)
- if (BX_SELECTED_IS_HD(channel)) {
- BX_DEBUG(("write cmd 0x70 (SEEK) executing"));
- if (!calculate_logical_address(channel, &logical_sector)) {
- BX_ERROR(("initial seek to sector %lu out of bounds, aborting", (unsigned long)logical_sector));
- command_aborted(channel, value);
- break;
- }
- BX_SELECTED_CONTROLLER(channel).error_register = 0;
- BX_SELECTED_CONTROLLER(channel).status.busy = 0;
- BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1;
- BX_SELECTED_CONTROLLER(channel).status.seek_complete = 1;
- BX_SELECTED_CONTROLLER(channel).status.drq = 0;
- BX_SELECTED_CONTROLLER(channel).status.corrected_data = 0;
- BX_SELECTED_CONTROLLER(channel).status.err = 0;
- BX_SELECTED_CONTROLLER(channel).buffer_index = 0;
- BX_DEBUG(("s[0].controller.control.disable_irq = %02x", (BX_HD_THIS channels[channel].drives[0]).controller.control.disable_irq));
- BX_DEBUG(("s[1].controller.control.disable_irq = %02x", (BX_HD_THIS channels[channel].drives[1]).controller.control.disable_irq));
- BX_DEBUG(("SEEK completed. error_register = %02x", BX_SELECTED_CONTROLLER(channel).error_register));
- raise_interrupt(channel);
- BX_DEBUG(("SEEK interrupt completed"));
- } else {
- BX_ERROR(("write cmd 0x70 (SEEK) not supported for non-disk"));
- command_aborted(channel, 0x70);
- }
- break;
-
-
-
- // List all the write operations that are defined in the ATA/ATAPI spec
- // that we don't support. Commands that are listed here will cause a
- // BX_ERROR, which is non-fatal, and the command will be aborted.
- case 0x22: BX_ERROR(("write cmd 0x22 (READ LONG) not supported")); command_aborted(channel, 0x22); break;
- case 0x23: BX_ERROR(("write cmd 0x23 (READ LONG NO RETRY) not supported")); command_aborted(channel, 0x23); break;
- case 0x24: BX_ERROR(("write cmd 0x24 (READ SECTORS EXT) not supported"));command_aborted(channel, 0x24); break;
- case 0x25: BX_ERROR(("write cmd 0x25 (READ DMA EXT) not supported"));command_aborted(channel, 0x25); break;
- case 0x26: BX_ERROR(("write cmd 0x26 (READ DMA QUEUED EXT) not supported"));command_aborted(channel, 0x26); break;
- case 0x27: BX_ERROR(("write cmd 0x27 (READ NATIVE MAX ADDRESS EXT) not supported"));command_aborted(channel, 0x27); break;
- case 0x29: BX_ERROR(("write cmd 0x29 (READ MULTIPLE EXT) not supported"));command_aborted(channel, 0x29); break;
- case 0x2A: BX_ERROR(("write cmd 0x2A (READ STREAM DMA) not supported"));command_aborted(channel, 0x2A); break;
- case 0x2B: BX_ERROR(("write cmd 0x2B (READ STREAM PIO) not supported"));command_aborted(channel, 0x2B); break;
- case 0x2F: BX_ERROR(("write cmd 0x2F (READ LOG EXT) not supported"));command_aborted(channel, 0x2F); break;
- case 0x31: BX_ERROR(("write cmd 0x31 (WRITE SECTORS NO RETRY) not supported")); command_aborted(channel, 0x31); break;
- case 0x32: BX_ERROR(("write cmd 0x32 (WRITE LONG) not supported")); command_aborted(channel, 0x32); break;
- case 0x33: BX_ERROR(("write cmd 0x33 (WRITE LONG NO RETRY) not supported")); command_aborted(channel, 0x33); break;
- case 0x34: BX_ERROR(("write cmd 0x34 (WRITE SECTORS EXT) not supported"));command_aborted(channel, 0x34); break;
- case 0x35: BX_ERROR(("write cmd 0x35 (WRITE DMA EXT) not supported"));command_aborted(channel, 0x35); break;
- case 0x36: BX_ERROR(("write cmd 0x36 (WRITE DMA QUEUED EXT) not supported"));command_aborted(channel, 0x36); break;
- case 0x37: BX_ERROR(("write cmd 0x37 (SET MAX ADDRESS EXT) not supported"));command_aborted(channel, 0x37); break;
- case 0x38: BX_ERROR(("write cmd 0x38 (CFA WRITE SECTORS W/OUT ERASE) not supported"));command_aborted(channel, 0x38); break;
- case 0x39: BX_ERROR(("write cmd 0x39 (WRITE MULTIPLE EXT) not supported"));command_aborted(channel, 0x39); break;
- case 0x3A: BX_ERROR(("write cmd 0x3A (WRITE STREAM DMA) not supported"));command_aborted(channel, 0x3A); break;
- case 0x3B: BX_ERROR(("write cmd 0x3B (WRITE STREAM PIO) not supported"));command_aborted(channel, 0x3B); break;
- case 0x3F: BX_ERROR(("write cmd 0x3F (WRITE LOG EXT) not supported"));command_aborted(channel, 0x3F); break;
- case 0x41: BX_ERROR(("write cmd 0x41 (READ VERIFY SECTORS NO RETRY) not supported")); command_aborted(channel, 0x41); break;
- case 0x42: BX_ERROR(("write cmd 0x42 (READ VERIFY SECTORS EXT) not supported"));command_aborted(channel, 0x42); break;
- case 0x50: BX_ERROR(("write cmd 0x50 (FORMAT TRACK) not supported")); command_aborted(channel, 0x50); break;
- case 0x51: BX_ERROR(("write cmd 0x51 (CONFIGURE STREAM) not supported"));command_aborted(channel, 0x51); break;
- case 0x87: BX_ERROR(("write cmd 0x87 (CFA TRANSLATE SECTOR) not supported"));command_aborted(channel, 0x87); break;
- case 0x92: BX_ERROR(("write cmd 0x92 (DOWNLOAD MICROCODE) not supported"));command_aborted(channel, 0x92); break;
- case 0x94: BX_ERROR(("write cmd 0x94 (STANDBY IMMEDIATE) not supported")); command_aborted(channel, 0x94); break;
- case 0x95: BX_ERROR(("write cmd 0x95 (IDLE IMMEDIATE) not supported")); command_aborted(channel, 0x95); break;
- case 0x96: BX_ERROR(("write cmd 0x96 (STANDBY) not supported")); command_aborted(channel, 0x96); break;
- case 0x97: BX_ERROR(("write cmd 0x97 (IDLE) not supported")); command_aborted(channel, 0x97); break;
- case 0x98: BX_ERROR(("write cmd 0x98 (CHECK POWER MODE) not supported")); command_aborted(channel, 0x98); break;
- case 0x99: BX_ERROR(("write cmd 0x99 (SLEEP) not supported")); command_aborted(channel, 0x99); break;
- case 0xB0: BX_ERROR(("write cmd 0xB0 (SMART commands) not supported"));command_aborted(channel, 0xB0); break;
- case 0xB1: BX_ERROR(("write cmd 0xB1 (DEVICE CONFIGURATION commands) not supported"));command_aborted(channel, 0xB1); break;
- case 0xC0: BX_ERROR(("write cmd 0xC0 (CFA ERASE SECTORS) not supported"));command_aborted(channel, 0xC0); break;
- case 0xC4: BX_ERROR(("write cmd 0xC4 (READ MULTIPLE) not supported"));command_aborted(channel, 0xC4); break;
- case 0xC5: BX_ERROR(("write cmd 0xC5 (WRITE MULTIPLE) not supported"));command_aborted(channel, 0xC5); break;
- case 0xC7: BX_ERROR(("write cmd 0xC7 (READ DMA QUEUED) not supported"));command_aborted(channel, 0xC7); break;
- case 0xC8: BX_ERROR(("write cmd 0xC8 (READ DMA) not supported"));command_aborted(channel, 0xC8); break;
- case 0xC9: BX_ERROR(("write cmd 0xC9 (READ DMA NO RETRY) not supported")); command_aborted(channel, 0xC9); break;
- case 0xCA: BX_ERROR(("write cmd 0xCA (WRITE DMA) not supported"));command_aborted(channel, 0xCA); break;
- case 0xCC: BX_ERROR(("write cmd 0xCC (WRITE DMA QUEUED) not supported"));command_aborted(channel, 0xCC); break;
- case 0xCD: BX_ERROR(("write cmd 0xCD (CFA WRITE MULTIPLE W/OUT ERASE) not supported"));command_aborted(channel, 0xCD); break;
- case 0xD1: BX_ERROR(("write cmd 0xD1 (CHECK MEDIA CARD TYPE) not supported"));command_aborted(channel, 0xD1); break;
- case 0xDA: BX_ERROR(("write cmd 0xDA (GET MEDIA STATUS) not supported"));command_aborted(channel, 0xDA); break;
- case 0xDE: BX_ERROR(("write cmd 0xDE (MEDIA LOCK) not supported"));command_aborted(channel, 0xDE); break;
- case 0xDF: BX_ERROR(("write cmd 0xDF (MEDIA UNLOCK) not supported"));command_aborted(channel, 0xDF); break;
- case 0xE0: BX_ERROR(("write cmd 0xE0 (STANDBY IMMEDIATE) not supported"));command_aborted(channel, 0xE0); break;
- case 0xE1: BX_ERROR(("write cmd 0xE1 (IDLE IMMEDIATE) not supported"));command_aborted(channel, 0xE1); break;
- case 0xE2: BX_ERROR(("write cmd 0xE2 (STANDBY) not supported"));command_aborted(channel, 0xE2); break;
- case 0xE3: BX_ERROR(("write cmd 0xE3 (IDLE) not supported"));command_aborted(channel, 0xE3); break;
- case 0xE4: BX_ERROR(("write cmd 0xE4 (READ BUFFER) not supported"));command_aborted(channel, 0xE4); break;
- case 0xE6: BX_ERROR(("write cmd 0xE6 (SLEEP) not supported"));command_aborted(channel, 0xE6); break;
- case 0xE7: BX_ERROR(("write cmd 0xE7 (FLUSH CACHE) not supported"));command_aborted(channel, 0xE7); break;
- case 0xE8: BX_ERROR(("write cmd 0xE8 (WRITE BUFFER) not supported"));command_aborted(channel, 0xE8); break;
- case 0xEA: BX_ERROR(("write cmd 0xEA (FLUSH CACHE EXT) not supported"));command_aborted(channel, 0xEA); break;
- case 0xED: BX_ERROR(("write cmd 0xED (MEDIA EJECT) not supported"));command_aborted(channel, 0xED); break;
- case 0xF1: BX_ERROR(("write cmd 0xF1 (SECURITY SET PASSWORD) not supported"));command_aborted(channel, 0xF1); break;
- case 0xF2: BX_ERROR(("write cmd 0xF2 (SECURITY UNLOCK) not supported"));command_aborted(channel, 0xF2); break;
- case 0xF3: BX_ERROR(("write cmd 0xF3 (SECURITY ERASE PREPARE) not supported"));command_aborted(channel, 0xF3); break;
- case 0xF4: BX_ERROR(("write cmd 0xF4 (SECURITY ERASE UNIT) not supported"));command_aborted(channel, 0xF4); break;
- case 0xF5: BX_ERROR(("write cmd 0xF5 (SECURITY FREEZE LOCK) not supported"));command_aborted(channel, 0xF5); break;
- case 0xF6: BX_ERROR(("write cmd 0xF6 (SECURITY DISABLE PASSWORD) not supported"));command_aborted(channel, 0xF6); break;
- case 0xF8: BX_ERROR(("write cmd 0xF8 (READ NATIVE MAX ADDRESS) not supported"));command_aborted(channel, 0xF8); break;
- case 0xF9: BX_ERROR(("write cmd 0xF9 (SET MAX ADDRESS) not supported"));command_aborted(channel, 0xF9); break;
-
- default:
- BX_PANIC(("IO write(0x%04x): command 0x%02x", address, (unsigned) value));
- // if user foolishly decides to continue, abort the command
- // so that the software knows the drive didn't understand it.
- command_aborted(channel, value);
- }
- break;
-
- case 0x16: // hard disk adapter control 0x3f6
- // (mch) Even if device 1 was selected, a write to this register
- // goes to device 0 (if device 1 is absent)
-
- prev_control_reset = BX_SELECTED_CONTROLLER(channel).control.reset;
- BX_HD_THIS channels[channel].drives[0].controller.control.reset = value & 0x04;
- BX_HD_THIS channels[channel].drives[1].controller.control.reset = value & 0x04;
- // CGS: was: BX_SELECTED_CONTROLLER(channel).control.disable_irq = value & 0x02;
- BX_HD_THIS channels[channel].drives[0].controller.control.disable_irq = value & 0x02;
- BX_HD_THIS channels[channel].drives[1].controller.control.disable_irq = value & 0x02;
-
- BX_DEBUG(( "adpater control reg: reset controller = %d",
- (unsigned) (BX_SELECTED_CONTROLLER(channel).control.reset) ? 1 : 0 ));
- BX_DEBUG(( "adpater control reg: disable_irq(X) = %d",
- (unsigned) (BX_SELECTED_CONTROLLER(channel).control.disable_irq) ? 1 : 0 ));
-
- if (!prev_control_reset && BX_SELECTED_CONTROLLER(channel).control.reset) {
- // transition from 0 to 1 causes all drives to reset
- BX_DEBUG(("hard drive: RESET"));
-
- // (mch) Set BSY, drive not ready
- for (int id = 0; id < 2; id++) {
- BX_CONTROLLER(channel,id).status.busy = 1;
- BX_CONTROLLER(channel,id).status.drive_ready = 0;
- BX_CONTROLLER(channel,id).reset_in_progress = 1;
-
- BX_CONTROLLER(channel,id).status.write_fault = 0;
- BX_CONTROLLER(channel,id).status.seek_complete = 1;
- BX_CONTROLLER(channel,id).status.drq = 0;
- BX_CONTROLLER(channel,id).status.corrected_data = 0;
- BX_CONTROLLER(channel,id).status.err = 0;
-
- BX_CONTROLLER(channel,id).error_register = 0x01; // diagnostic code: no error
-
- BX_CONTROLLER(channel,id).current_command = 0x00;
- BX_CONTROLLER(channel,id).buffer_index = 0;
-
- BX_CONTROLLER(channel,id).sectors_per_block = 0x80;
- BX_CONTROLLER(channel,id).lba_mode = 0;
-
- BX_CONTROLLER(channel,id).control.disable_irq = 0;
- DEV_pic_lower_irq(BX_HD_THIS channels[channel].irq);
- }
- } else if (BX_SELECTED_CONTROLLER(channel).reset_in_progress &&
- !BX_SELECTED_CONTROLLER(channel).control.reset) {
- // Clear BSY and DRDY
- BX_DEBUG(("Reset complete {%s}", BX_SELECTED_TYPE_STRING(channel)));
- for (int id = 0; id < 2; id++) {
- BX_CONTROLLER(channel,id).status.busy = 0;
- BX_CONTROLLER(channel,id).status.drive_ready = 1;
- BX_CONTROLLER(channel,id).reset_in_progress = 0;
-
- // Device signature
- if (BX_DRIVE_IS_HD(channel,id)) {
- BX_CONTROLLER(channel,id).head_no = 0;
- BX_CONTROLLER(channel,id).sector_count = 1;
- BX_CONTROLLER(channel,id).sector_no = 1;
- BX_CONTROLLER(channel,id).cylinder_no = 0;
- } else {
- BX_CONTROLLER(channel,id).head_no = 0;
- BX_CONTROLLER(channel,id).sector_count = 1;
- BX_CONTROLLER(channel,id).sector_no = 1;
- BX_CONTROLLER(channel,id).cylinder_no = 0xeb14;
- }
- }
- }
- BX_DEBUG(("s[0].controller.control.disable_irq = %02x", (BX_HD_THIS channels[channel].drives[0]).controller.control.disable_irq));
- BX_DEBUG(("s[1].controller.control.disable_irq = %02x", (BX_HD_THIS channels[channel].drives[1]).controller.control.disable_irq));
- break;
-
- default:
- BX_PANIC(("hard drive: io write to address %x = %02x",
- (unsigned) address, (unsigned) value));
- }
-}
-
- void
-bx_hard_drive_c::close_harddrive(void)
-{
- for (Bit8u channel=0; channel<BX_MAX_ATA_CHANNEL; channel++) {
- if(BX_HD_THIS channels[channel].drives[0].hard_drive != NULL)
- BX_HD_THIS channels[channel].drives[0].hard_drive->close();
- if(BX_HD_THIS channels[channel].drives[1].hard_drive != NULL)
- BX_HD_THIS channels[channel].drives[1].hard_drive->close();
- }
-}
-
-
- bx_bool BX_CPP_AttrRegparmN(2)
-bx_hard_drive_c::calculate_logical_address(Bit8u channel, off_t *sector)
-{
- off_t logical_sector;
-
- if (BX_SELECTED_CONTROLLER(channel).lba_mode) {
- //bx_printf ("disk: calculate: %d %d %d\n", ((Bit32u)BX_SELECTED_CONTROLLER(channel).head_no), ((Bit32u)BX_SELECTED_CONTROLLER(channel).cylinder_no), (Bit32u)BX_SELECTED_CONTROLLER(channel).sector_no);
- logical_sector = ((Bit32u)BX_SELECTED_CONTROLLER(channel).head_no) << 24 |
- ((Bit32u)BX_SELECTED_CONTROLLER(channel).cylinder_no) << 8 |
- (Bit32u)BX_SELECTED_CONTROLLER(channel).sector_no;
- //bx_printf ("disk: result: %u\n", logical_sector);
- } else
- logical_sector = (BX_SELECTED_CONTROLLER(channel).cylinder_no * BX_SELECTED_DRIVE(channel).hard_drive->heads *
- BX_SELECTED_DRIVE(channel).hard_drive->sectors) +
- (BX_SELECTED_CONTROLLER(channel).head_no * BX_SELECTED_DRIVE(channel).hard_drive->sectors) +
- (BX_SELECTED_CONTROLLER(channel).sector_no - 1);
-
- Bit32u sector_count=
- (Bit32u)BX_SELECTED_DRIVE(channel).hard_drive->cylinders *
- (Bit32u)BX_SELECTED_DRIVE(channel).hard_drive->heads *
- (Bit32u)BX_SELECTED_DRIVE(channel).hard_drive->sectors;
-
- if (logical_sector >= sector_count) {
- BX_ERROR (("calc_log_addr: out of bounds (%d/%d)", (Bit32u)logical_sector, sector_count));
- return false;
- }
- *sector = logical_sector;
- return true;
-}
-
- void BX_CPP_AttrRegparmN(1)
-bx_hard_drive_c::increment_address(Bit8u channel)
-{
- BX_SELECTED_CONTROLLER(channel).sector_count--;
-
- if (BX_SELECTED_CONTROLLER(channel).lba_mode) {
- off_t current_address;
- calculate_logical_address(channel, ¤t_address);
- current_address++;
- BX_SELECTED_CONTROLLER(channel).head_no = (Bit8u)((current_address >> 24) & 0xf);
- BX_SELECTED_CONTROLLER(channel).cylinder_no = (Bit16u)((current_address >> 8) & 0xffff);
- BX_SELECTED_CONTROLLER(channel).sector_no = (Bit8u)((current_address) & 0xff);
- } else {
- BX_SELECTED_CONTROLLER(channel).sector_no++;
- if (BX_SELECTED_CONTROLLER(channel).sector_no > BX_SELECTED_DRIVE(channel).hard_drive->sectors) {
- BX_SELECTED_CONTROLLER(channel).sector_no = 1;
- BX_SELECTED_CONTROLLER(channel).head_no++;
- if (BX_SELECTED_CONTROLLER(channel).head_no >= BX_SELECTED_DRIVE(channel).hard_drive->heads) {
- BX_SELECTED_CONTROLLER(channel).head_no = 0;
- BX_SELECTED_CONTROLLER(channel).cylinder_no++;
- if (BX_SELECTED_CONTROLLER(channel).cylinder_no >= BX_SELECTED_DRIVE(channel).hard_drive->cylinders)
- BX_SELECTED_CONTROLLER(channel).cylinder_no = BX_SELECTED_DRIVE(channel).hard_drive->cylinders - 1;
- }
- }
- }
-}
-
- void
-bx_hard_drive_c::identify_ATAPI_drive(Bit8u channel)
-{
- unsigned i;
-
- BX_SELECTED_DRIVE(channel).id_drive[0] = (2 << 14) | (5 << 8) | (1 << 7) | (2 << 5) | (0 << 0); // Removable CDROM, 50us response, 12 byte packets
-
- for (i = 1; i <= 9; i++)
- BX_SELECTED_DRIVE(channel).id_drive[i] = 0;
-
- const char* serial_number = " VT00001\0\0\0\0\0\0\0\0\0\0\0\0";
- for (i = 0; i < 10; i++) {
- BX_SELECTED_DRIVE(channel).id_drive[10+i] = (serial_number[i*2] << 8) |
- serial_number[i*2 + 1];
- }
-
- for (i = 20; i <= 22; i++)
- BX_SELECTED_DRIVE(channel).id_drive[i] = 0;
-
- const char* firmware = "ALPHA1 ";
- for (i = 0; i < strlen(firmware)/2; i++) {
- BX_SELECTED_DRIVE(channel).id_drive[23+i] = (firmware[i*2] << 8) |
- firmware[i*2 + 1];
- }
- BX_ASSERT((23+i) == 27);
-
- for (i = 0; i < strlen((char *) BX_SELECTED_MODEL(channel))/2; i++) {
- BX_SELECTED_DRIVE(channel).id_drive[27+i] = (BX_SELECTED_MODEL(channel)[i*2] << 8) |
- BX_SELECTED_MODEL(channel)[i*2 + 1];
- }
- BX_ASSERT((27+i) == 47);
-
- BX_SELECTED_DRIVE(channel).id_drive[47] = 0;
- BX_SELECTED_DRIVE(channel).id_drive[48] = 1; // 32 bits access
-
- BX_SELECTED_DRIVE(channel).id_drive[49] = (1 << 9); // LBA supported
-
- BX_SELECTED_DRIVE(channel).id_drive[50] = 0;
- BX_SELECTED_DRIVE(channel).id_drive[51] = 0;
- BX_SELECTED_DRIVE(channel).id_drive[52] = 0;
-
- BX_SELECTED_DRIVE(channel).id_drive[53] = 3; // words 64-70, 54-58 valid
-
- for (i = 54; i <= 62; i++)
- BX_SELECTED_DRIVE(channel).id_drive[i] = 0;
-
- // copied from CFA540A
- BX_SELECTED_DRIVE(channel).id_drive[63] = 0x0103; // variable (DMA stuff)
- BX_SELECTED_DRIVE(channel).id_drive[64] = 0x0001; // PIO
- BX_SELECTED_DRIVE(channel).id_drive[65] = 0x00b4;
- BX_SELECTED_DRIVE(channel).id_drive[66] = 0x00b4;
- BX_SELECTED_DRIVE(channel).id_drive[67] = 0x012c;
- BX_SELECTED_DRIVE(channel).id_drive[68] = 0x00b4;
-
- BX_SELECTED_DRIVE(channel).id_drive[69] = 0;
- BX_SELECTED_DRIVE(channel).id_drive[70] = 0;
- BX_SELECTED_DRIVE(channel).id_drive[71] = 30; // faked
- BX_SELECTED_DRIVE(channel).id_drive[72] = 30; // faked
- BX_SELECTED_DRIVE(channel).id_drive[73] = 0;
- BX_SELECTED_DRIVE(channel).id_drive[74] = 0;
-
- BX_SELECTED_DRIVE(channel).id_drive[75] = 0;
-
- for (i = 76; i <= 79; i++)
- BX_SELECTED_DRIVE(channel).id_drive[i] = 0;
-
- BX_SELECTED_DRIVE(channel).id_drive[80] = 0x1e; // supports up to ATA/ATAPI-4
- BX_SELECTED_DRIVE(channel).id_drive[81] = 0;
- BX_SELECTED_DRIVE(channel).id_drive[82] = 0;
- BX_SELECTED_DRIVE(channel).id_drive[83] = 0;
- BX_SELECTED_DRIVE(channel).id_drive[84] = 0;
- BX_SELECTED_DRIVE(channel).id_drive[85] = 0;
- BX_SELECTED_DRIVE(channel).id_drive[86] = 0;
- BX_SELECTED_DRIVE(channel).id_drive[87] = 0;
- BX_SELECTED_DRIVE(channel).id_drive[88] = 0;
-
- for (i = 89; i <= 126; i++)
- BX_SELECTED_DRIVE(channel).id_drive[i] = 0;
-
- BX_SELECTED_DRIVE(channel).id_drive[127] = 0;
- BX_SELECTED_DRIVE(channel).id_drive[128] = 0;
-
- for (i = 129; i <= 159; i++)
- BX_SELECTED_DRIVE(channel).id_drive[i] = 0;
-
- for (i = 160; i <= 255; i++)
- BX_SELECTED_DRIVE(channel).id_drive[i] = 0;
-
- // now convert the id_drive array (native 256 word format) to
- // the controller buffer (512 bytes)
- Bit16u temp16;
- for (i = 0; i <= 255; i++) {
- temp16 = BX_SELECTED_DRIVE(channel).id_drive[i];
- BX_SELECTED_CONTROLLER(channel).buffer[i*2] = temp16 & 0x00ff;
- BX_SELECTED_CONTROLLER(channel).buffer[i*2+1] = temp16 >> 8;
- }
-}
-
- void
-bx_hard_drive_c::identify_drive(Bit8u channel)
-{
- unsigned i;
- Bit32u temp32;
- Bit16u temp16;
-
-#if defined(CONNER_CFA540A)
- BX_SELECTED_DRIVE(channel).id_drive[0] = 0x0c5a;
- BX_SELECTED_DRIVE(channel).id_drive[1] = 0x0418;
- BX_SELECTED_DRIVE(channel).id_drive[2] = 0;
- BX_SELECTED_DRIVE(channel).id_drive[3] = BX_SELECTED_DRIVE(channel).hard_drive->heads;
- BX_SELECTED_DRIVE(channel).id_drive[4] = 0x9fb7;
- BX_SELECTED_DRIVE(channel).id_drive[5] = 0x0289;
- BX_SELECTED_DRIVE(channel).id_drive[6] = BX_SELECTED_DRIVE(channel).hard_drive->sectors;
- BX_SELECTED_DRIVE(channel).id_drive[7] = 0x0030;
- BX_SELECTED_DRIVE(channel).id_drive[8] = 0x000a;
- BX_SELECTED_DRIVE(channel).id_drive[9] = 0x0000;
-
- char* serial_number = " CA00GSQ\0\0\0\0\0\0\0\0\0\0\0\0";
- for (i = 0; i < 10; i++) {
- BX_SELECTED_DRIVE(channel).id_drive[10+i] = (serial_number[i*2] << 8) |
- serial_number[i*2 + 1];
- }
-
- BX_SELECTED_DRIVE(channel).id_drive[20] = 3;
- BX_SELECTED_DRIVE(channel).id_drive[21] = 512; // 512 Sectors = 256kB cache
- BX_SELECTED_DRIVE(channel).id_drive[22] = 4;
-
- char* firmware = "8FT054 ";
- for (i = 0; i < strlen(firmware)/2; i++) {
- BX_SELECTED_DRIVE(channel).id_drive[23+i] = (firmware[i*2] << 8) |
- firmware[i*2 + 1];
- }
- BX_ASSERT((23+i) == 27);
-
- char* model = "Conner Peripherals 540MB - CFA540A ";
- for (i = 0; i < strlen(model)/2; i++) {
- BX_SELECTED_DRIVE(channel).id_drive[27+i] = (model[i*2] << 8) |
- model[i*2 + 1];
- }
- BX_ASSERT((27+i) == 47);
-
- BX_SELECTED_DRIVE(channel).id_drive[47] = 0x8080; // multiple mode identification
- BX_SELECTED_DRIVE(channel).id_drive[48] = 0;
- BX_SELECTED_DRIVE(channel).id_drive[49] = 0x0f01;
-
- BX_SELECTED_DRIVE(channel).id_drive[50] = 0;
-
- BX_SELECTED_DRIVE(channel).id_drive[51] = 0;
- BX_SELECTED_DRIVE(channel).id_drive[52] = 0x0002;
- BX_SELECTED_DRIVE(channel).id_drive[53] = 0x0003;
- BX_SELECTED_DRIVE(channel).id_drive[54] = 0x0418;
-
- BX_SELECTED_DRIVE(channel).id_drive[55] = BX_SELECTED_DRIVE(channel).hard_drive->heads;
- BX_SELECTED_DRIVE(channel).id_drive[56] = BX_SELECTED_DRIVE(channel).hard_drive->sectors;
-
- BX_SELECTED_DRIVE(channel).id_drive[57] = 0x1e80;
- BX_SELECTED_DRIVE(channel).id_drive[58] = 0x0010;
- BX_SELECTED_DRIVE(channel).id_drive[59] = 0x0100 | BX_SELECTED_CONTROLLER(channel).sectors_per_block;
- BX_SELECTED_DRIVE(channel).id_drive[60] = 0x20e0;
- BX_SELECTED_DRIVE(channel).id_drive[61] = 0x0010;
-
- BX_SELECTED_DRIVE(channel).id_drive[62] = 0;
-
- BX_SELECTED_DRIVE(channel).id_drive[63] = 0x0103; // variable (DMA stuff)
- BX_SELECTED_DRIVE(channel).id_drive[64] = 0x0001; // PIO
- BX_SELECTED_DRIVE(channel).id_drive[65] = 0x00b4;
- BX_SELECTED_DRIVE(channel).id_drive[66] = 0x00b4;
- BX_SELECTED_DRIVE(channel).id_drive[67] = 0x012c;
- BX_SELECTED_DRIVE(channel).id_drive[68] = 0x00b4;
-
- for (i = 69; i <= 79; i++)
- BX_SELECTED_DRIVE(channel).id_drive[i] = 0;
-
- BX_SELECTED_DRIVE(channel).id_drive[80] = 0;
-
- BX_SELECTED_DRIVE(channel).id_drive[81] = 0;
-
- BX_SELECTED_DRIVE(channel).id_drive[82] = 0;
- BX_SELECTED_DRIVE(channel).id_drive[83] = 0;
- BX_SELECTED_DRIVE(channel).id_drive[84] = 0;
- BX_SELECTED_DRIVE(channel).id_drive[85] = 0;
- BX_SELECTED_DRIVE(channel).id_drive[86] = 0;
- BX_SELECTED_DRIVE(channel).id_drive[87] = 0;
-
- for (i = 88; i <= 127; i++)
- BX_SELECTED_DRIVE(channel).id_drive[i] = 0;
-
- BX_SELECTED_DRIVE(channel).id_drive[128] = 0x0418;
- BX_SELECTED_DRIVE(channel).id_drive[129] = 0x103f;
- BX_SELECTED_DRIVE(channel).id_drive[130] = 0x0418;
- BX_SELECTED_DRIVE(channel).id_drive[131] = 0x103f;
- BX_SELECTED_DRIVE(channel).id_drive[132] = 0x0004;
- BX_SELECTED_DRIVE(channel).id_drive[133] = 0xffff;
- BX_SELECTED_DRIVE(channel).id_drive[134] = 0;
- BX_SELECTED_DRIVE(channel).id_drive[135] = 0x5050;
-
- for (i = 136; i <= 144; i++)
- BX_SELECTED_DRIVE(channel).id_drive[i] = 0;
-
- BX_SELECTED_DRIVE(channel).id_drive[145] = 0x302e;
- BX_SELECTED_DRIVE(channel).id_drive[146] = 0x3245;
- BX_SELECTED_DRIVE(channel).id_drive[147] = 0x2020;
- BX_SELECTED_DRIVE(channel).id_drive[148] = 0x2020;
-
- for (i = 149; i <= 255; i++)
- BX_SELECTED_DRIVE(channel).id_drive[i] = 0;
-
-#else
-
- // Identify Drive command return values definition
- //
- // This code is rehashed from some that was donated.
- // I'm using ANSI X3.221-1994, AT Attachment Interface for Disk Drives
- // and X3T10 2008D Working Draft for ATA-3
-
-
- // Word 0: general config bit-significant info
- // Note: bits 1-5 and 8-14 are now "Vendor specific (obsolete)"
- // bit 15: 0=ATA device
- // 1=ATAPI device
- // bit 14: 1=format speed tolerance gap required
- // bit 13: 1=track offset option available
- // bit 12: 1=data strobe offset option available
- // bit 11: 1=rotational speed tolerance is > 0,5% (typo?)
- // bit 10: 1=disk transfer rate > 10Mbs
- // bit 9: 1=disk transfer rate > 5Mbs but <= 10Mbs
- // bit 8: 1=disk transfer rate <= 5Mbs
- // bit 7: 1=removable cartridge drive
- // bit 6: 1=fixed drive
- // bit 5: 1=spindle motor control option implemented
- // bit 4: 1=head switch time > 15 usec
- // bit 3: 1=not MFM encoded
- // bit 2: 1=soft sectored
- // bit 1: 1=hard sectored
- // bit 0: 0=reserved
- BX_SELECTED_DRIVE(channel).id_drive[0] = 0x0040;
-
- // Word 1: number of user-addressable cylinders in
- // default translation mode. If the value in words 60-61
- // exceed 16,515,072, this word shall contain 16,383.
- BX_SELECTED_DRIVE(channel).id_drive[1] = BX_SELECTED_DRIVE(channel).hard_drive->cylinders;
-
- // Word 2: reserved
- BX_SELECTED_DRIVE(channel).id_drive[2] = 0;
-
- // Word 3: number of user-addressable heads in default
- // translation mode
- BX_SELECTED_DRIVE(channel).id_drive[3] = BX_SELECTED_DRIVE(channel).hard_drive->heads;
-
- // Word 4: # unformatted bytes per translated track in default xlate mode
- // Word 5: # unformatted bytes per sector in default xlated mode
- // Word 6: # user-addressable sectors per track in default xlate mode
- // Note: words 4,5 are now "Vendor specific (obsolete)"
- BX_SELECTED_DRIVE(channel).id_drive[4] = (512 * BX_SELECTED_DRIVE(channel).hard_drive->sectors);
- BX_SELECTED_DRIVE(channel).id_drive[5] = 512;
- BX_SELECTED_DRIVE(channel).id_drive[6] = BX_SELECTED_DRIVE(channel).hard_drive->sectors;
-
- // Word 7-9: Vendor specific
- for (i=7; i<=9; i++)
- BX_SELECTED_DRIVE(channel).id_drive[i] = 0;
-
- // Word 10-19: Serial number (20 ASCII characters, 0000h=not specified)
- // This field is right justified and padded with spaces (20h).
- for (i=10; i<=19; i++)
- BX_SELECTED_DRIVE(channel).id_drive[i] = 0;
-
- // Word 20: buffer type
- // 0000h = not specified
- // 0001h = single ported single sector buffer which is
- // not capable of simulataneous data xfers to/from
- // the host and the disk.
- // 0002h = dual ported multi-sector buffer capable of
- // simulatenous data xfers to/from the host and disk.
- // 0003h = dual ported mutli-sector buffer capable of
- // simulatenous data xfers with a read caching
- // capability.
- // 0004h-ffffh = reserved
- BX_SELECTED_DRIVE(channel).id_drive[20] = 3;
-
- // Word 21: buffer size in 512 byte increments, 0000h = not specified
- BX_SELECTED_DRIVE(channel).id_drive[21] = 512; // 512 Sectors = 256kB cache
-
- // Word 22: # of ECC bytes available on read/write long cmds
- // 0000h = not specified
- BX_SELECTED_DRIVE(channel).id_drive[22] = 4;
-
- // Word 23..26: Firmware revision (8 ascii chars, 0000h=not specified)
- // This field is left justified and padded with spaces (20h)
- for (i=23; i<=26; i++)
- BX_SELECTED_DRIVE(channel).id_drive[i] = 0;
-
- // Word 27..46: Model number (40 ascii chars, 0000h=not specified)
- // This field is left justified and padded with spaces (20h)
-// for (i=27; i<=46; i++)
-// BX_SELECTED_DRIVE(channel).id_drive[i] = 0;
- for (i=0; i<20; i++) {
- BX_SELECTED_DRIVE(channel).id_drive[27+i] = (BX_SELECTED_MODEL(channel)[i*2] << 8) |
- BX_SELECTED_MODEL(channel)[i*2 + 1];
- }
-
- // Word 47: 15-8 Vendor unique
- // 7-0 00h= read/write multiple commands not implemented
- // xxh= maximum # of sectors that can be transferred
- // per interrupt on read and write multiple commands
- BX_SELECTED_DRIVE(channel).id_drive[47] = max_multiple_sectors;
-
- // Word 48: 0000h = cannot perform dword IO
- // 0001h = can perform dword IO
- BX_SELECTED_DRIVE(channel).id_drive[48] = 1;
-
- // Word 49: Capabilities
- // 15-10: 0 = reserved
- // 9: 1 = LBA supported
- // 8: 1 = DMA supported
- // 7-0: Vendor unique
- BX_SELECTED_DRIVE(channel).id_drive[49] = 1<<9;
-
- // Word 50: Reserved
- BX_SELECTED_DRIVE(channel).id_drive[50] = 0;
-
- // Word 51: 15-8 PIO data transfer cycle timing mode
- // 7-0 Vendor unique
- BX_SELECTED_DRIVE(channel).id_drive[51] = 0x200;
-
- // Word 52: 15-8 DMA data transfer cycle timing mode
- // 7-0 Vendor unique
- BX_SELECTED_DRIVE(channel).id_drive[52] = 0x200;
-
- // Word 53: 15-1 Reserved
- // 0 1=the fields reported in words 54-58 are valid
- // 0=the fields reported in words 54-58 may be valid
- BX_SELECTED_DRIVE(channel).id_drive[53] = 0;
-
- // Word 54: # of user-addressable cylinders in curr xlate mode
- // Word 55: # of user-addressable heads in curr xlate mode
- // Word 56: # of user-addressable sectors/track in curr xlate mode
- BX_SELECTED_DRIVE(channel).id_drive[54] = BX_SELECTED_DRIVE(channel).hard_drive->cylinders;
- BX_SELECTED_DRIVE(channel).id_drive[55] = BX_SELECTED_DRIVE(channel).hard_drive->heads;
- BX_SELECTED_DRIVE(channel).id_drive[56] = BX_SELECTED_DRIVE(channel).hard_drive->sectors;
-
- // Word 57-58: Current capacity in sectors
- // Excludes all sectors used for device specific purposes.
- temp32 =
- BX_SELECTED_DRIVE(channel).hard_drive->cylinders *
- BX_SELECTED_DRIVE(channel).hard_drive->heads *
- BX_SELECTED_DRIVE(channel).hard_drive->sectors;
- BX_SELECTED_DRIVE(channel).id_drive[57] = (temp32 & 0xffff); // LSW
- BX_SELECTED_DRIVE(channel).id_drive[58] = (temp32 >> 16); // MSW
-
- // Word 59: 15-9 Reserved
- // 8 1=multiple sector setting is valid
- // 7-0 current setting for number of sectors that can be
- // transferred per interrupt on R/W multiple commands
- BX_SELECTED_DRIVE(channel).id_drive[59] = 0x0000 | curr_multiple_sectors;
-
- // Word 60-61:
- // If drive supports LBA Mode, these words reflect total # of user
- // addressable sectors. This value does not depend on the current
- // drive geometry. If the drive does not support LBA mode, these
- // words shall be set to 0.
- Bit32u num_sects = BX_SELECTED_DRIVE(channel).hard_drive->cylinders * BX_SELECTED_DRIVE(channel).hard_drive->heads * BX_SELECTED_DRIVE(channel).hard_drive->sectors;
- BX_SELECTED_DRIVE(channel).id_drive[60] = num_sects & 0xffff; // LSW
- BX_SELECTED_DRIVE(channel).id_drive[61] = num_sects >> 16; // MSW
-
- // Word 62: 15-8 single word DMA transfer mode active
- // 7-0 single word DMA transfer modes supported
- // The low order byte identifies by bit, all the Modes which are
- // supported e.g., if Mode 0 is supported bit 0 is set.
- // The high order byte contains a single bit set to indiciate
- // which mode is active.
- BX_SELECTED_DRIVE(channel).id_drive[62] = 0x0;
-
- // Word 63: 15-8 multiword DMA transfer mode active
- // 7-0 multiword DMA transfer modes supported
- // The low order byte identifies by bit, all the Modes which are
- // supported e.g., if Mode 0 is supported bit 0 is set.
- // The high order byte contains a single bit set to indiciate
- // which mode is active.
- BX_SELECTED_DRIVE(channel).id_drive[63] = 0x0;
-
- // Word 64-79 Reserved
- for (i=64; i<=79; i++)
- BX_SELECTED_DRIVE(channel).id_drive[i] = 0;
-
- // Word 80: 15-5 reserved
- // 4 supports ATA/ATAPI-4
- // 3 supports ATA-3
- // 2 supports ATA-2
- // 1 supports ATA-1
- // 0 reserved
- BX_SELECTED_DRIVE(channel).id_drive[80] = (1 << 2) | (1 << 1);
-
- // Word 81: Minor version number
- BX_SELECTED_DRIVE(channel).id_drive[81] = 0;
-
- // Word 82: 15 obsolete
- // 14 NOP command supported
- // 13 READ BUFFER command supported
- // 12 WRITE BUFFER command supported
- // 11 obsolete
- // 10 Host protected area feature set supported
- // 9 DEVICE RESET command supported
- // 8 SERVICE interrupt supported
- // 7 release interrupt supported
- // 6 look-ahead supported
- // 5 write cache supported
- // 4 supports PACKET command feature set
- // 3 supports power management feature set
- // 2 supports removable media feature set
- // 1 supports securite mode feature set
- // 0 support SMART feature set
- BX_SELECTED_DRIVE(channel).id_drive[82] = 1 << 14;
- BX_SELECTED_DRIVE(channel).id_drive[83] = 1 << 14;
- BX_SELECTED_DRIVE(channel).id_drive[84] = 1 << 14;
- BX_SELECTED_DRIVE(channel).id_drive[85] = 1 << 14;
- BX_SELECTED_DRIVE(channel).id_drive[86] = 0;
- BX_SELECTED_DRIVE(channel).id_drive[87] = 1 << 14;
-
- for (i=88; i<=127; i++)
- BX_SELECTED_DRIVE(channel).id_drive[i] = 0;
-
- // Word 128-159 Vendor unique
- for (i=128; i<=159; i++)
- BX_SELECTED_DRIVE(channel).id_drive[i] = 0;
-
- // Word 160-255 Reserved
- for (i=160; i<=255; i++)
- BX_SELECTED_DRIVE(channel).id_drive[i] = 0;
-
-#endif
-
- BX_DEBUG(("Drive ID Info. initialized : %04d {%s}", 512, BX_SELECTED_TYPE_STRING(channel)));
-
- // now convert the id_drive array (native 256 word format) to
- // the controller buffer (512 bytes)
- for (i=0; i<=255; i++) {
- temp16 = BX_SELECTED_DRIVE(channel).id_drive[i];
- BX_SELECTED_CONTROLLER(channel).buffer[i*2] = temp16 & 0x00ff;
- BX_SELECTED_CONTROLLER(channel).buffer[i*2+1] = temp16 >> 8;
- }
-}
-
- void BX_CPP_AttrRegparmN(3)
-bx_hard_drive_c::init_send_atapi_command(Bit8u channel, Bit8u command, int req_length, int alloc_length, bool lazy)
-{
- // BX_SELECTED_CONTROLLER(channel).byte_count is a union of BX_SELECTED_CONTROLLER(channel).cylinder_no;
- // lazy is used to force a data read in the buffer at the next read.
-
- if (BX_SELECTED_CONTROLLER(channel).byte_count == 0xffff)
- BX_SELECTED_CONTROLLER(channel).byte_count = 0xfffe;
-
- if ((BX_SELECTED_CONTROLLER(channel).byte_count & 1)
- && !(alloc_length <= BX_SELECTED_CONTROLLER(channel).byte_count)) {
- BX_INFO(("Odd byte count (0x%04x) to ATAPI command 0x%02x, using 0x%04x",
- BX_SELECTED_CONTROLLER(channel).byte_count, command, BX_SELECTED_CONTROLLER(channel).byte_count - 1));
- BX_SELECTED_CONTROLLER(channel).byte_count -= 1;
- }
-
- if (BX_SELECTED_CONTROLLER(channel).byte_count == 0)
- BX_PANIC(("ATAPI command with zero byte count"));
-
- if (alloc_length < 0)
- BX_PANIC(("Allocation length < 0"));
- if (alloc_length == 0)
- alloc_length = BX_SELECTED_CONTROLLER(channel).byte_count;
-
- BX_SELECTED_CONTROLLER(channel).interrupt_reason.i_o = 1;
- BX_SELECTED_CONTROLLER(channel).interrupt_reason.c_d = 0;
- BX_SELECTED_CONTROLLER(channel).status.busy = 0;
- BX_SELECTED_CONTROLLER(channel).status.drq = 1;
- BX_SELECTED_CONTROLLER(channel).status.err = 0;
-
- // no bytes transfered yet
- if (lazy)
- BX_SELECTED_CONTROLLER(channel).buffer_index = 2048;
- else
- BX_SELECTED_CONTROLLER(channel).buffer_index = 0;
- BX_SELECTED_CONTROLLER(channel).drq_index = 0;
-
- if (BX_SELECTED_CONTROLLER(channel).byte_count > req_length)
- BX_SELECTED_CONTROLLER(channel).byte_count = req_length;
-
- if (BX_SELECTED_CONTROLLER(channel).byte_count > alloc_length)
- BX_SELECTED_CONTROLLER(channel).byte_count = alloc_length;
-
- BX_SELECTED_DRIVE(channel).atapi.command = command;
- BX_SELECTED_DRIVE(channel).atapi.drq_bytes = BX_SELECTED_CONTROLLER(channel).byte_count;
- BX_SELECTED_DRIVE(channel).atapi.total_bytes_remaining = (req_length < alloc_length) ? req_length : alloc_length;
-
- // if (lazy) {
- // // bias drq_bytes and total_bytes_remaining
- // BX_SELECTED_DRIVE(channel).atapi.drq_bytes += 2048;
- // BX_SELECTED_DRIVE(channel).atapi.total_bytes_remaining += 2048;
- // }
-}
-
-void
-bx_hard_drive_c::atapi_cmd_error(Bit8u channel, sense_t sense_key, asc_t asc)
-{
- BX_ERROR(("atapi_cmd_error channel=%02x key=%02x asc=%02x", channel, sense_key, asc));
-
- BX_SELECTED_CONTROLLER(channel).error_register = sense_key << 4;
- BX_SELECTED_CONTROLLER(channel).interrupt_reason.i_o = 1;
- BX_SELECTED_CONTROLLER(channel).interrupt_reason.c_d = 1;
- BX_SELECTED_CONTROLLER(channel).interrupt_reason.rel = 0;
- BX_SELECTED_CONTROLLER(channel).status.busy = 0;
- BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1;
- BX_SELECTED_CONTROLLER(channel).status.write_fault = 0;
- BX_SELECTED_CONTROLLER(channel).status.drq = 0;
- BX_SELECTED_CONTROLLER(channel).status.err = 1;
-
- BX_SELECTED_DRIVE(channel).sense.sense_key = sense_key;
- BX_SELECTED_DRIVE(channel).sense.asc = asc;
- BX_SELECTED_DRIVE(channel).sense.ascq = 0;
-}
-
-void BX_CPP_AttrRegparmN(1)
-bx_hard_drive_c::atapi_cmd_nop(Bit8u channel)
-{
- BX_SELECTED_CONTROLLER(channel).interrupt_reason.i_o = 1;
- BX_SELECTED_CONTROLLER(channel).interrupt_reason.c_d = 1;
- BX_SELECTED_CONTROLLER(channel).interrupt_reason.rel = 0;
- BX_SELECTED_CONTROLLER(channel).status.busy = 0;
- BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1;
- BX_SELECTED_CONTROLLER(channel).status.drq = 0;
- BX_SELECTED_CONTROLLER(channel).status.err = 0;
-}
-
-void
-bx_hard_drive_c::init_mode_sense_single(Bit8u channel, const void* src, int size)
-{
- // Header
- BX_SELECTED_CONTROLLER(channel).buffer[0] = (size+6) >> 8;
- BX_SELECTED_CONTROLLER(channel).buffer[1] = (size+6) & 0xff;
- BX_SELECTED_CONTROLLER(channel).buffer[2] = 0x70; // no media present
- BX_SELECTED_CONTROLLER(channel).buffer[3] = 0; // reserved
- BX_SELECTED_CONTROLLER(channel).buffer[4] = 0; // reserved
- BX_SELECTED_CONTROLLER(channel).buffer[5] = 0; // reserved
- BX_SELECTED_CONTROLLER(channel).buffer[6] = 0; // reserved
- BX_SELECTED_CONTROLLER(channel).buffer[7] = 0; // reserved
-
- // Data
- memcpy(BX_SELECTED_CONTROLLER(channel).buffer + 8, src, size);
-}
-
- void BX_CPP_AttrRegparmN(1)
-bx_hard_drive_c::ready_to_send_atapi(Bit8u channel)
-{
- raise_interrupt(channel);
-}
-
-void BX_CPP_AttrRegparmN(1)
-bx_hard_drive_c::raise_interrupt(Bit8u channel)
-{
- BX_DEBUG(("raise_interrupt called, disable_irq = %02x", BX_SELECTED_CONTROLLER(channel).control.disable_irq));
- if (!BX_SELECTED_CONTROLLER(channel).control.disable_irq) { BX_DEBUG(("raising interrupt")); } else { BX_DEBUG(("Not raising interrupt")); }
- if (!BX_SELECTED_CONTROLLER(channel).control.disable_irq) {
- Bit32u irq = BX_HD_THIS channels[channel].irq;
- BX_DEBUG(("Raising interrupt %d {%s}", irq, BX_SELECTED_TYPE_STRING(channel)));
- DEV_pic_raise_irq(irq);
- } else {
- if (bx_dbg.disk || (BX_SELECTED_IS_CD(channel) && bx_dbg.cdrom))
- BX_INFO(("Interrupt masked {%s}", BX_SELECTED_TYPE_STRING(channel)));
- }
-}
-
- void
-bx_hard_drive_c::command_aborted(Bit8u channel, unsigned value)
-{
- BX_DEBUG(("aborting on command 0x%02x {%s}", value, BX_SELECTED_TYPE_STRING(channel)));
- BX_SELECTED_CONTROLLER(channel).current_command = 0;
- BX_SELECTED_CONTROLLER(channel).status.busy = 0;
- BX_SELECTED_CONTROLLER(channel).status.drive_ready = 1;
- BX_SELECTED_CONTROLLER(channel).status.err = 1;
- BX_SELECTED_CONTROLLER(channel).error_register = 0x04; // command ABORTED
- BX_SELECTED_CONTROLLER(channel).status.drq = 0;
- BX_SELECTED_CONTROLLER(channel).status.seek_complete = 0;
- BX_SELECTED_CONTROLLER(channel).status.corrected_data = 0;
- BX_SELECTED_CONTROLLER(channel).buffer_index = 0;
- raise_interrupt(channel);
-}
-
- Bit32u
-bx_hard_drive_c::get_device_handle(Bit8u channel, Bit8u device)
-{
- BX_DEBUG(("get_device_handle %d %d",channel, device));
- if ((channel < BX_MAX_ATA_CHANNEL) && (device < 2)) {
- return ((channel*2) + device);
- }
-
- return BX_MAX_ATA_CHANNEL*2;
-}
-
- Bit32u
-bx_hard_drive_c::get_first_cd_handle(void)
-{
- for (Bit8u channel=0; channel<BX_MAX_ATA_CHANNEL; channel++) {
- if (BX_DRIVE_IS_CD(channel,0)) return (channel*2);
- if (BX_DRIVE_IS_CD(channel,1)) return ((channel*2) + 1);
- }
- return BX_MAX_ATA_CHANNEL*2;
-}
-
- unsigned
-bx_hard_drive_c::get_cd_media_status(Bit32u handle)
-{
- if ( handle >= BX_MAX_ATA_CHANNEL*2 ) return 0;
-
- Bit8u channel = handle / 2;
- Bit8u device = handle % 2;
- return( BX_HD_THIS channels[channel].drives[device].cdrom.ready );
-}
-
- unsigned
-bx_hard_drive_c::set_cd_media_status(Bit32u handle, unsigned status)
-{
- BX_DEBUG (("set_cd_media_status handle=%d status=%d", handle, status));
- if ( handle >= BX_MAX_ATA_CHANNEL*2 ) return 0;
-
- Bit8u channel = handle / 2;
- Bit8u device = handle % 2;
-
- // if setting to the current value, nothing to do
- if (status == BX_HD_THIS channels[channel].drives[device].cdrom.ready)
- return(status);
- // return 0 if no cdromd is present
- if (!BX_DRIVE_IS_CD(channel,device))
- return(0);
-
- if (status == 0) {
- // eject cdrom if not locked by guest OS
- if (BX_HD_THIS channels[channel].drives[device].cdrom.locked) return(1);
- else {
-#ifdef LOWLEVEL_CDROM
- BX_HD_THIS channels[channel].drives[device].cdrom.cd->eject_cdrom();
-#endif
- BX_HD_THIS channels[channel].drives[device].cdrom.ready = 0;
- bx_options.atadevice[channel][device].Ostatus->set(BX_EJECTED);
- }
- }
- else {
- // insert cdrom
-#ifdef LOWLEVEL_CDROM
- if (BX_HD_THIS channels[channel].drives[device].cdrom.cd->insert_cdrom(bx_options.atadevice[channel][device].Opath->getptr())) {
- BX_INFO(( "Media present in CD-ROM drive"));
- BX_HD_THIS channels[channel].drives[device].cdrom.ready = 1;
- BX_HD_THIS channels[channel].drives[device].cdrom.capacity = BX_HD_THIS channels[channel].drives[device].cdrom.cd->capacity();
- bx_options.atadevice[channel][device].Ostatus->set(BX_INSERTED);
- BX_SELECTED_DRIVE(channel).sense.sense_key = SENSE_UNIT_ATTENTION;
- BX_SELECTED_DRIVE(channel).sense.asc = 0;
- BX_SELECTED_DRIVE(channel).sense.ascq = 0;
- raise_interrupt(channel);
- }
- else {
-#endif
- BX_INFO(( "Could not locate CD-ROM, continuing with media not present"));
- BX_HD_THIS channels[channel].drives[device].cdrom.ready = 0;
- bx_options.atadevice[channel][device].Ostatus->set(BX_EJECTED);
-#ifdef LOWLEVEL_CDROM
- }
-#endif
- }
- return( BX_HD_THIS channels[channel].drives[device].cdrom.ready );
-}
-
-
-/*** default_image_t function definitions ***/
-
-int default_image_t::open (const char* pathname)
-{
- return open(pathname, O_RDWR);
-}
-
-int default_image_t::open (const char* pathname, int flags)
-{
- fd = ::open(pathname, flags
-#ifdef O_BINARY
- | O_BINARY
-#endif
- );
-
- if (fd < 0) {
- return fd;
- }
-
- /* look at size of image file to calculate disk geometry */
- struct stat stat_buf;
- int ret = fstat(fd, &stat_buf);
- if (ret) {
- BX_PANIC(("fstat() returns error!"));
- }
-
- return fd;
-}
-
-void default_image_t::close ()
-{
- if (fd > -1) {
- ::close(fd);
- }
-}
-
-off_t default_image_t::lseek (off_t offset, int whence)
-{
- return ::lseek(fd, offset, whence);
-}
-
-ssize_t default_image_t::read (void* buf, size_t count)
-{
- return ::read(fd, (char*) buf, count);
-}
-
-ssize_t default_image_t::write (const void* buf, size_t count)
-{
- return ::write(fd, (char*) buf, count);
-}
-
-char increment_string (char *str, int diff)
-{
- // find the last character of the string, and increment it.
- char *p = str;
- while (*p != 0) p++;
- BX_ASSERT (p>str); // choke on zero length strings
- p--; // point to last character of the string
- (*p) += diff; // increment to next/previous ascii code.
- BX_DEBUG(("increment string returning '%s'", str));
- return (*p);
-}
-
-/*** concat_image_t function definitions ***/
-
-concat_image_t::concat_image_t ()
-{
- fd = -1;
-}
-
-void concat_image_t::increment_string (char *str)
-{
- ::increment_string(str, +1);
-}
-
-int concat_image_t::open (const char* pathname0)
-{
- char *pathname = strdup (pathname0);
- BX_DEBUG(("concat_image_t.open"));
- off_t start_offset = 0;
- for (int i=0; i<BX_CONCAT_MAX_IMAGES; i++) {
- fd_table[i] = ::open(pathname, O_RDWR
-#ifdef O_BINARY
- | O_BINARY
-#endif
- );
- if (fd_table[i] < 0) {
- // open failed.
- // if no FD was opened successfully, return -1 (fail).
- if (i==0) return -1;
- // otherwise, it only means that all images in the series have
- // been opened. Record the number of fds opened successfully.
- maxfd = i;
- break;
- }
- BX_DEBUG(("concat_image: open image %s, fd[%d] = %d", pathname, i, fd_table[i]));
- /* look at size of image file to calculate disk geometry */
- struct stat stat_buf;
- int ret = fstat(fd_table[i], &stat_buf);
- if (ret) {
- BX_PANIC(("fstat() returns error!"));
- }
-#ifdef S_ISBLK
- if (S_ISBLK(stat_buf.st_mode)) {
- BX_PANIC(("block devices should REALLY NOT be used with --enable-split-hd. "
- "Please reconfigure with --disable-split-hd"));
- }
-#endif
- if ((stat_buf.st_size % 512) != 0) {
- BX_PANIC(("size of disk image must be multiple of 512 bytes"));
- }
- length_table[i] = stat_buf.st_size;
- start_offset_table[i] = start_offset;
- start_offset += stat_buf.st_size;
- increment_string (pathname);
- }
- // start up with first image selected
- index = 0;
- fd = fd_table[0];
- thismin = 0;
- thismax = length_table[0]-1;
- seek_was_last_op = 0;
- return 0; // success.
-}
-
-void concat_image_t::close ()
-{
- BX_DEBUG(("concat_image_t.close"));
- if (fd > -1) {
- ::close(fd);
- }
-}
-
-off_t concat_image_t::lseek (off_t offset, int whence)
-{
- if ((offset % 512) != 0)
- BX_PANIC( ("lseek HD with offset not multiple of 512"));
- BX_DEBUG(("concat_image_t.lseek(%d)", whence));
- // is this offset in this disk image?
- if (offset < thismin) {
- // no, look at previous images
- for (int i=index-1; i>=0; i--) {
- if (offset >= start_offset_table[i]) {
- index = i;
- fd = fd_table[i];
- thismin = start_offset_table[i];
- thismax = thismin + length_table[i] - 1;
- BX_DEBUG(("concat_image_t.lseek to earlier image, index=%d", index));
- break;
- }
- }
- } else if (offset > thismax) {
- // no, look at later images
- for (int i=index+1; i<maxfd; i++) {
- if (offset < start_offset_table[i] + length_table[i]) {
- index = i;
- fd = fd_table[i];
- thismin = start_offset_table[i];
- thismax = thismin + length_table[i] - 1;
- BX_DEBUG(("concat_image_t.lseek to earlier image, index=%d", index));
- break;
- }
- }
- }
- // now offset should be within the current image.
- offset -= start_offset_table[index];
- if (offset < 0 || offset >= length_table[index]) {
- BX_PANIC(("concat_image_t.lseek to byte %ld failed", (long)offset));
- return -1;
- }
-
- seek_was_last_op = 1;
- return ::lseek(fd, offset, whence);
-}
-
-ssize_t concat_image_t::read (void* buf, size_t count)
-{
- if (bx_dbg.disk)
- BX_DEBUG(("concat_image_t.read %ld bytes", (long)count));
- // notice if anyone does sequential read or write without seek in between.
- // This can be supported pretty easily, but needs additional checks for
- // end of a partial image.
- if (!seek_was_last_op)
- BX_PANIC( ("no seek before read"));
- return ::read(fd, (char*) buf, count);
-}
-
-ssize_t concat_image_t::write (const void* buf, size_t count)
-{
- BX_DEBUG(("concat_image_t.write %ld bytes", (long)count));
- // notice if anyone does sequential read or write without seek in between.
- // This can be supported pretty easily, but needs additional checks for
- // end of a partial image.
- if (!seek_was_last_op)
- BX_PANIC( ("no seek before write"));
- return ::write(fd, (char*) buf, count);
-}
-
-/*** sparse_image_t function definitions ***/
-sparse_image_t::sparse_image_t ()
-{
- fd = -1;
- pathname = NULL;
-#ifdef _POSIX_MAPPED_FILES
- mmap_header = NULL;
-#endif
- pagetable = NULL;
-}
-
-
-/*
-void showpagetable(uint32 * pagetable, size_t numpages)
-{
- printf("Non null pages: ");
- for (int i = 0; i < numpages; i++)
- {
- if (pagetable[i] != 0xffffffff)
- {
- printf("%d ", i);
- }
- }
- printf("\n");
-}
-*/
-
-
-void sparse_image_t::read_header()
-{
- BX_ASSERT(sizeof(header) == SPARSE_HEADER_SIZE);
-
- int ret = ::read(fd, &header, sizeof(header));
-
- if (-1 == ret)
- {
- panic(strerror(errno));
- }
-
- if (sizeof(header) != ret)
- {
- panic("could not read entire header");
- }
-
- if (dtoh32(header.magic) != SPARSE_HEADER_MAGIC)
- {
- panic("failed header magic check");
- }
-
- if (dtoh32(header.version) != 1)
- {
- panic("unknown version in header");
- }
-
- pagesize = dtoh32(header.pagesize);
- uint32 numpages = dtoh32(header.numpages);
-
- total_size = pagesize;
- total_size *= numpages;
-
- pagesize_shift = 0;
- while ((pagesize >> pagesize_shift) > 1) pagesize_shift++;
-
- if ((uint32)(1 << pagesize_shift) != pagesize)
- {
- panic("failed block size header check");
- }
-
- pagesize_mask = pagesize - 1;
-
- size_t preamble_size = (sizeof(uint32) * numpages) + sizeof(header);
- data_start = 0;
- while (data_start < preamble_size) data_start += pagesize;
-
- bool did_mmap = false;
-
-#ifdef _POSIX_MAPPED_FILES
-// Try to memory map from the beginning of the file (0 is trivially a page multiple)
- void * mmap_header = mmap(NULL, preamble_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
- if (mmap_header == MAP_FAILED)
- {
- BX_INFO(("failed to mmap sparse disk file - using conventional file access"));
- mmap_header = NULL;
- }
- else
- {
- mmap_length = preamble_size;
- did_mmap = true;
- pagetable = ((uint32 *) (((uint8 *) mmap_header) + sizeof(header)));
-
-// system_pagesize = getpagesize();
- system_pagesize_mask = getpagesize() - 1;
- }
-#endif
-
- if (!did_mmap)
- {
- pagetable = new uint32[numpages];
-
- if (pagetable == NULL)
- {
- panic("could not allocate memory for sparse disk block table");
- }
-
- ret = ::read(fd, pagetable, sizeof(uint32) * numpages);
-
- if (-1 == ret)
- {
- panic(strerror(errno));
- }
-
- if ((int)(sizeof(uint32) * numpages) != ret)
- {
- panic("could not read entire block table");
- }
- }
-}
-
-int sparse_image_t::open (const char* pathname0)
-{
- pathname = strdup(pathname0);
- BX_DEBUG(("sparse_image_t.open"));
-
- fd = ::open(pathname, O_RDWR
-#ifdef O_BINARY
- | O_BINARY
-#endif
- );
-
- if (fd < 0)
- {
- // open failed.
- return -1;
- }
- BX_DEBUG(("sparse_image: open image %s", pathname));
-
- read_header();
-
- struct stat stat_buf;
- if (0 != fstat(fd, &stat_buf)) panic(("fstat() returns error!"));
-
- underlying_filesize = stat_buf.st_size;
-
- if ((underlying_filesize % pagesize) != 0)
- panic("size of sparse disk image is not multiple of page size");
-
- underlying_current_filepos = 0;
- if (-1 == ::lseek(fd, 0, SEEK_SET))
- panic("error while seeking to start of file");
-
- lseek(0, SEEK_SET);
-
- //showpagetable(pagetable, header.numpages);
-
- char * parentpathname = strdup(pathname);
- char lastchar = ::increment_string(parentpathname, -1);
-
- if ((lastchar >= '0') && (lastchar <= '9'))
- {
- struct stat stat_buf;
- if (0 == stat(parentpathname, &stat_buf))
- {
- parent_image = new sparse_image_t();
- int ret = parent_image->open(parentpathname);
- if (ret != 0) return ret;
- if ( (parent_image->pagesize != pagesize)
- || (parent_image->total_size != total_size))
- {
- panic("child drive image does not have same page count/page size configuration");
- }
- }
- }
-
- if (parentpathname != NULL) free(parentpathname);
-
- return 0; // success.
-}
-
-void sparse_image_t::close ()
-{
- BX_DEBUG(("concat_image_t.close"));
- if (pathname != NULL)
- {
- free(pathname);
- }
-#ifdef _POSIX_MAPPED_FILES
- if (mmap_header != NULL)
- {
- int ret = munmap(mmap_header, mmap_length);
- if (ret != 0)
- BX_INFO(("failed to un-memory map sparse disk file"));
- }
- pagetable = NULL; // We didn't malloc it
-#endif
- if (fd > -1) {
- ::close(fd);
- }
- if (pagetable != NULL)
- {
- delete [] pagetable;
- }
- if (parent_image != NULL)
- {
- delete parent_image;
- }
-}
-
-off_t sparse_image_t::lseek (off_t offset, int whence)
-{
- //showpagetable(pagetable, header.numpages);
-
- if ((offset % 512) != 0)
- BX_PANIC( ("lseek HD with offset not multiple of 512"));
- if (whence != SEEK_SET)
- BX_PANIC( ("lseek HD with whence not SEEK_SET"));
-
- BX_DEBUG(("sparse_image_t.lseek(%d)", whence));
-
- if (offset > total_size)
- {
- BX_PANIC(("sparse_image_t.lseek to byte %ld failed", (long)offset));
- return -1;
- }
-
- //printf("Seeking to position %ld\n", (long) offset);
-
- set_virtual_page(offset >> pagesize_shift);
- position_page_offset = offset & pagesize_mask;
-
- return 0;
-}
-
-inline off_t sparse_image_t::get_physical_offset()
-{
- off_t physical_offset = data_start;
- physical_offset += (position_physical_page << pagesize_shift);
- physical_offset += position_page_offset;
-
- return physical_offset;
-}
-
-inline void sparse_image_t::set_virtual_page(uint32 new_virtual_page)
-{
- position_virtual_page = new_virtual_page;
-
- position_physical_page = dtoh32(pagetable[position_virtual_page]);
-}
-
-ssize_t sparse_image_t::read_page_fragment(uint32 read_virtual_page, uint32 read_page_offset, size_t read_size, void * buf)
-{
- if (read_virtual_page != position_virtual_page)
- {
- set_virtual_page(read_virtual_page);
- }
-
- position_page_offset = read_page_offset;
-
- if (position_physical_page == SPARSE_PAGE_NOT_ALLOCATED)
- {
- if (parent_image != NULL)
- {
- return parent_image->read_page_fragment(read_virtual_page, read_page_offset, read_size, buf);
- }
- else
- {
- memset(buf, 0, read_size);
- }
- }
- else
- {
- off_t physical_offset = get_physical_offset();
-
- if (physical_offset != underlying_current_filepos)
- {
- int ret = ::lseek(fd, physical_offset, SEEK_SET);
- // underlying_current_filepos update deferred
- if (ret == -1)
- panic(strerror(errno));
- }
-
- //printf("Reading %s at position %ld size %d\n", pathname, (long) physical_offset, (long) read_size);
- ssize_t readret = ::read(fd, buf, read_size);
-
- if (readret == -1)
- {
- panic(strerror(errno));
- }
-
- if ((size_t)readret != read_size)
- {
- panic("could not read block contents from file");
- }
-
- underlying_current_filepos = physical_offset + read_size;
- }
-
- return read_size;
-}
-
-ssize_t sparse_image_t::read(void* buf, size_t count)
-{
- //showpagetable(pagetable, header.numpages);
- ssize_t total_read = 0;
-
- if (bx_dbg.disk)
- BX_DEBUG(("sparse_image_t.read %ld bytes", (long)count));
-
- while (count != 0)
- {
- size_t can_read = pagesize - position_page_offset;
- if (count < can_read) can_read = count;
-
- BX_ASSERT (can_read != 0);
-
- size_t was_read = read_page_fragment(position_virtual_page, position_page_offset, can_read, buf);
-
- BX_ASSERT(was_read == can_read);
-
- total_read += can_read;
-
- position_page_offset += can_read;
- if (position_page_offset == pagesize)
- {
- position_page_offset = 0;
- set_virtual_page(position_virtual_page + 1);
- }
-
- BX_ASSERT(position_page_offset < pagesize);
-
- buf = (((uint8 *) buf) + can_read);
- count -= can_read;
- }
-
- return total_read;
-}
-
-void sparse_image_t::panic(const char * message)
-{
- char buffer[1024];
- if (message == NULL)
- {
- snprintf(buffer, sizeof(buffer), "error with sparse disk image %s", pathname);
- }
- else
- {
- snprintf(buffer, sizeof(buffer), "error with sparse disk image %s - %s", pathname, message);
- }
- BX_PANIC((buffer));
-}
-
-ssize_t sparse_image_t::write (const void* buf, size_t count)
-{
- //showpagetable(pagetable, header.numpages);
-
- ssize_t total_written = 0;
-
- uint32 update_pagetable_start = position_virtual_page;
- uint32 update_pagetable_count = 0;
-
- if (bx_dbg.disk)
- BX_DEBUG(("sparse_image_t.write %ld bytes", (long)count));
-
- while (count != 0)
- {
- size_t can_write = pagesize - position_page_offset;
- if (count < can_write) can_write = count;
-
- BX_ASSERT (can_write != 0);
-
- if (position_physical_page == SPARSE_PAGE_NOT_ALLOCATED)
- {
- // We just add on another page at the end of the file
- // Reclamation, compaction etc should currently be done off-line
-
- size_t data_size = underlying_filesize - data_start;
- BX_ASSERT((data_size % pagesize) == 0);
-
-
- uint32 data_size_pages = data_size / pagesize;
- uint32 next_data_page = data_size_pages;
-
- pagetable[position_virtual_page] = htod32(next_data_page);
- position_physical_page = next_data_page;
-
- off_t page_file_start = data_start + (position_physical_page << pagesize_shift);
-
- if (parent_image != NULL)
- {
- // If we have a parent, we must merge our portion with the parent
- void * writebuffer = NULL;
-
- if (can_write == pagesize)
- {
- writebuffer = (void *) buf;
- }
- else
- {
- writebuffer = malloc(pagesize);
- if (writebuffer == NULL)
- panic("Cannot allocate sufficient memory for page-merge in write");
-
- // Read entire page - could optimize, but simple for now
- parent_image->read_page_fragment(position_virtual_page, 0, pagesize, writebuffer);
-
- void * dest_start = ((uint8 *) writebuffer) + position_page_offset;
- memcpy(dest_start, buf, can_write);
- }
-
- int ret;
- ret = ::lseek(fd, page_file_start, SEEK_SET);
- // underlying_current_filepos update deferred
- if (-1 == ret) panic(strerror(errno));
-
- ret = ::write(fd, writebuffer, pagesize);
-
- if (-1 == ret) panic(strerror(errno));
-
- if (pagesize != (uint32)ret) panic("failed to write entire merged page to disk");
-
- if (can_write != pagesize)
- {
- free(writebuffer);
- }
- }
- else
- {
- // We need to write a zero page because read has been returning zeroes
- // We seek as close to the page end as possible, and then write a little
- // This produces a sparse file which has blanks
- // Also very quick, even when pagesize is massive
- int ret;
- ret = ::lseek(fd, page_file_start + pagesize - 4, SEEK_SET);
- // underlying_current_filepos update deferred
- if (-1 == ret) panic(strerror(errno));
-
- uint32 zero = 0;
- ret = ::write(fd, &zero, 4);
-
- if (-1 == ret) panic(strerror(errno));
-
- if (4 != ret) panic("failed to write entire blank page to disk");
- }
-
- update_pagetable_count = (position_virtual_page - update_pagetable_start) + 1;
- underlying_filesize = underlying_current_filepos = page_file_start + pagesize;
- }
-
- BX_ASSERT(position_physical_page != SPARSE_PAGE_NOT_ALLOCATED);
-
- off_t physical_offset = get_physical_offset();
-
- if (physical_offset != underlying_current_filepos)
- {
- int ret = ::lseek(fd, physical_offset, SEEK_SET);
- // underlying_current_filepos update deferred
- if (ret == -1)
- panic(strerror(errno));
- }
-
- //printf("Writing at position %ld size %d\n", (long) physical_offset, can_write);
- ssize_t writeret = ::write(fd, buf, can_write);
-
- if (writeret == -1)
- {
- panic(strerror(errno));
- }
-
- if ((size_t)writeret != can_write)
- {
- panic("could not write block contents to file");
- }
-
- underlying_current_filepos = physical_offset + can_write;
-
- total_written += can_write;
-
- position_page_offset += can_write;
- if (position_page_offset == pagesize)
- {
- position_page_offset = 0;
- set_virtual_page(position_virtual_page + 1);
- }
-
- BX_ASSERT(position_page_offset < pagesize);
-
- buf = (((uint8 *) buf) + can_write);
- count -= can_write;
- }
-
- if (update_pagetable_count != 0)
- {
- bool done = false;
- off_t pagetable_write_from = sizeof(header) + (sizeof(uint32) * update_pagetable_start);
- size_t write_bytecount = update_pagetable_count * sizeof(uint32);
-
-#ifdef _POSIX_MAPPED_FILES
- if (mmap_header != NULL)
- {
- // Sync from the beginning of the page
- size_t system_page_offset = pagetable_write_from & system_pagesize_mask;
- void * start = ((uint8 *) mmap_header + pagetable_write_from - system_page_offset);
-
- int ret = msync(start, system_page_offset + write_bytecount, MS_ASYNC);
-
- if (ret != 0)
- panic(strerror(errno));
-
- done = true;
- }
-#endif
-
- if (!done)
- {
- int ret = ::lseek(fd, pagetable_write_from, SEEK_SET);
- // underlying_current_filepos update deferred
- if (ret == -1) panic(strerror(errno));
-
- //printf("Writing header at position %ld size %ld\n", (long) pagetable_write_from, (long) write_bytecount);
- ret = ::write(fd, &pagetable[update_pagetable_start], write_bytecount);
- if (ret == -1) panic(strerror(errno));
- if ((size_t)ret != write_bytecount) panic("could not write entire updated block header");
-
- underlying_current_filepos = pagetable_write_from + write_bytecount;
- }
- }
-
- return total_written;
-}
-
-#if DLL_HD_SUPPORT
-/*** dll_image_t function definitions ***/
-
-/*
-function vdisk_open(path:PChar;numclusters,clustersize:integer):integer;
-procedure vdisk_read(vunit:integer;blk:integer;var buf:TBlock);
-procedure vdisk_write(vunit:integer;blk:integer;var buf:TBlock);
-procedure vdisk_close(vunit:integer);
-*/
-
-HINSTANCE hlib_vdisk = 0;
-
-int (*vdisk_open) (const char *path,int numclusters,int clustersize);
-void (*vdisk_read) (int vunit,int blk,void *buf);
-void (*vdisk_write) (int vunit,int blk,const void *buf);
-void (*vdisk_close) (int vunit);
-
-int dll_image_t::open (const char* pathname)
-{
- if (hlib_vdisk == 0) {
- hlib_vdisk = LoadLibrary("vdisk.dll");
- if (hlib_vdisk != 0) {
- vdisk_read = (void (*)(int,int,void*)) GetProcAddress(hlib_vdisk,"vdisk_read");
- vdisk_write = (void (*)(int,int,const void*)) GetProcAddress(hlib_vdisk,"vdisk_write");
- vdisk_open = (int (*)(const char *,int,int)) GetProcAddress(hlib_vdisk,"vdisk_open");
- vdisk_close = (void (*)(int)) GetProcAddress(hlib_vdisk,"vdisk_close");
- }
- }
- if (hlib_vdisk != 0) {
- vunit = vdisk_open(pathname,0x10000,64);
- vblk = 0;
- } else {
- vunit = -2;
- }
- return vunit;
-}
-
-void dll_image_t::close ()
-{
- if (vunit >= 0 && hlib_vdisk != 0) {
- vdisk_close(vunit);
- }
-}
-
-off_t dll_image_t::lseek (off_t offset, int whence)
-{
- vblk = offset >> 9;
- return 0;
-}
-
-ssize_t dll_image_t::read (void* buf, size_t count)
-{
- if (vunit >= 0 && hlib_vdisk != 0) {
- vdisk_read(vunit,vblk,buf);
- return count;
- } else {
- return -1;
- }
-}
-
-ssize_t dll_image_t::write (const void* buf, size_t count)
-{
- if (vunit >= 0 && hlib_vdisk != 0) {
- vdisk_write(vunit,vblk,buf);
- return count;
- } else {
- return -1;
- }
-}
-#endif // DLL_HD_SUPPORT
-
-error_recovery_t::error_recovery_t ()
-{
- if (sizeof(error_recovery_t) != 8) {
- BX_PANIC(("error_recovery_t has size != 8"));
- }
-
- data[0] = 0x01;
- data[1] = 0x06;
- data[2] = 0x00;
- data[3] = 0x05; // Try to recover 5 times
- data[4] = 0x00;
- data[5] = 0x00;
- data[6] = 0x00;
- data[7] = 0x00;
-}
-
-uint16 BX_CPP_AttrRegparmN(1)
-read_16bit(const uint8* buf)
-{
- return (buf[0] << 8) | buf[1];
-}
-
-uint32 BX_CPP_AttrRegparmN(1)
-read_32bit(const uint8* buf)
-{
- return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
-}
-
-// redolog implementation
-redolog_t::redolog_t ()
-{
- fd = -1;
- catalog = NULL;
- bitmap = NULL;
- extent_index = (Bit32u)0;
- extent_offset = (Bit32u)0;
- extent_next = (Bit32u)0;
-}
-
-void
-redolog_t::print_header()
-{
- BX_INFO(("redolog : Standard Header : magic='%s', type='%s', subtype='%s', version = %d.%d",
- header.standard.magic, header.standard.type, header.standard.subtype,
- dtoh32(header.standard.version)/0x10000,
- dtoh32(header.standard.version)%0x10000));
- BX_INFO(("redolog : Specific Header : #entries=%d, bitmap size=%d, exent size = %d disk size = %lld",
- dtoh32(header.specific.catalog),
- dtoh32(header.specific.bitmap),
- dtoh32(header.specific.extent),
- dtoh64(header.specific.disk)));
-}
-
-int
-redolog_t::make_header (const char* type, Bit64u size)
-{
- Bit32u entries, extent_size, bitmap_size;
- Bit64u maxsize;
- Bit32u flip=0;
-
- // Set standard header values
- strcpy((char*)header.standard.magic, STANDARD_HEADER_MAGIC);
- strcpy((char*)header.standard.type, REDOLOG_TYPE);
- strcpy((char*)header.standard.subtype, type);
- header.standard.version = htod32(STANDARD_HEADER_VERSION);
- header.standard.header = htod32(STANDARD_HEADER_SIZE);
-
- entries = 512;
- bitmap_size = 1;
-
- // Compute #entries and extent size values
- do {
- extent_size = 8 * bitmap_size * 512;
-
- header.specific.catalog = htod32(entries);
- header.specific.bitmap = htod32(bitmap_size);
- header.specific.extent = htod32(extent_size);
-
- maxsize = (Bit64u)entries * (Bit64u)extent_size;
-
- flip++;
-
- if(flip&0x01) bitmap_size *= 2;
- else entries *= 2;
- } while (maxsize < size);
-
- header.specific.disk = htod64(size);
-
- print_header();
-
- catalog = (Bit32u*)malloc(dtoh32(header.specific.catalog) * sizeof(Bit32u));
- bitmap = (Bit8u*)malloc(dtoh32(header.specific.bitmap));
-
- if ((catalog == NULL) || (bitmap==NULL))
- BX_PANIC(("redolog : could not malloc catalog or bitmap"));
-
- for (Bit32u i=0; i<dtoh32(header.specific.catalog); i++)
- catalog[i] = htod32(REDOLOG_PAGE_NOT_ALLOCATED);
-
- bitmap_blocs = 1 + (dtoh32(header.specific.bitmap) - 1) / 512;
- extent_blocs = 1 + (dtoh32(header.specific.extent) - 1) / 512;
-
- BX_DEBUG(("redolog : each bitmap is %d blocs", bitmap_blocs));
- BX_DEBUG(("redolog : each extent is %d blocs", extent_blocs));
-
- return 0;
-}
-
-int
-redolog_t::create (const char* filename, const char* type, Bit64u size)
-{
- int filedes;
-
- BX_INFO(("redolog : creating redolog %s", filename));
-
- filedes = ::open(filename, O_RDWR | O_CREAT | O_TRUNC
-#ifdef O_BINARY
- | O_BINARY
-#endif
- , S_IWUSR | S_IRUSR | S_IRGRP | S_IWGRP);
-
- return create(filedes, type, size);
-}
-
-int
-redolog_t::create (int filedes, const char* type, Bit64u size)
-{
- fd = filedes;
-
- if (fd < 0)
- {
- // open failed.
- return -1;
- }
-
- if (make_header(type, size) < 0)
- {
- return -1;
- }
-
- // Write header
- ::write(fd, &header, dtoh32(header.standard.header));
-
- // Write catalog
- // FIXME could mmap
- ::write(fd, catalog, dtoh32(header.specific.catalog) * sizeof (Bit32u));
-
- return 0;
-}
-
-int
-redolog_t::open (const char* filename, const char *type, Bit64u size)
-{
- int res;
-
- fd = ::open(filename, O_RDWR
-#ifdef O_BINARY
- | O_BINARY
-#endif
- );
- if (fd < 0)
- {
- BX_INFO(("redolog : could not open image %s", filename));
- // open failed.
- return -1;
- }
- BX_INFO(("redolog : open image %s", filename));
-
- res = ::read(fd, &header, sizeof(header));
- if (res != STANDARD_HEADER_SIZE)
- {
- BX_PANIC(("redolog : could not read header"));
- return -1;
- }
-
- print_header();
-
- if (strcmp((char*)header.standard.magic, STANDARD_HEADER_MAGIC) != 0)
- {
- BX_PANIC(("redolog : Bad header magic"));
- return -1;
- }
-
- if (strcmp((char*)header.standard.type, REDOLOG_TYPE) != 0)
- {
- BX_PANIC(("redolog : Bad header type"));
- return -1;
- }
- if (strcmp((char*)header.standard.subtype, type) != 0)
- {
- BX_PANIC(("redolog : Bad header subtype"));
- return -1;
- }
-
- if (dtoh32(header.standard.version) != STANDARD_HEADER_VERSION)
- {
- BX_PANIC(("redolog : Bad header version"));
- return -1;
- }
-
- catalog = (Bit32u*)malloc(dtoh32(header.specific.catalog) * sizeof(Bit32u));
-
- // FIXME could mmap
- ::lseek(fd,dtoh32(header.standard.header),SEEK_SET);
- res = ::read(fd, catalog, dtoh32(header.specific.catalog) * sizeof(Bit32u)) ;
-
- if (res != (ssize_t)(dtoh32(header.specific.catalog) * sizeof(Bit32u)))
- {
- BX_PANIC(("redolog : could not read catalog %d=%d",res, dtoh32(header.specific.catalog)));
- return -1;
- }
-
- // check last used extent
- extent_next = 0;
- for (Bit32u i=0; i < dtoh32(header.specific.catalog); i++)
- {
- if (dtoh32(catalog[i]) != REDOLOG_PAGE_NOT_ALLOCATED)
- {
- if (dtoh32(catalog[i]) >= extent_next)
- extent_next = dtoh32(catalog[i]) + 1;
- }
- }
- BX_INFO(("redolog : next extent will be at index %d",extent_next));
-
- // memory used for storing bitmaps
- bitmap = (Bit8u *)malloc(dtoh32(header.specific.bitmap));
-
- bitmap_blocs = 1 + (dtoh32(header.specific.bitmap) - 1) / 512;
- extent_blocs = 1 + (dtoh32(header.specific.extent) - 1) / 512;
-
- BX_DEBUG(("redolog : each bitmap is %d blocs", bitmap_blocs));
- BX_DEBUG(("redolog : each extent is %d blocs", extent_blocs));
-
- return 0;
-}
-
-void
-redolog_t::close ()
-{
- if (fd >= 0)
- ::close(fd);
-
- if (catalog != NULL)
- free(catalog);
-
- if (bitmap != NULL)
- free(bitmap);
-}
-
-off_t
-redolog_t::lseek (off_t offset, int whence)
-{
- if ((offset % 512) != 0) {
- BX_PANIC( ("redolog : lseek HD with offset not multiple of 512"));
- return -1;
- }
- if (whence != SEEK_SET) {
- BX_PANIC( ("redolog : lseek HD with whence not SEEK_SET"));
- return -1;
- }
- if (offset > (off_t)dtoh64(header.specific.disk))
- {
- BX_PANIC(("redolog : lseek to byte %ld failed", (long)offset));
- return -1;
- }
-
- extent_index = offset / dtoh32(header.specific.extent);
- extent_offset = (offset % dtoh32(header.specific.extent)) / 512;
-
- BX_DEBUG(("redolog : lseeking extent index %d, offset %d",extent_index, extent_offset));
-
- return offset;
-}
-
-ssize_t
-redolog_t::read (void* buf, size_t count)
-{
- off_t bloc_offset, bitmap_offset;
-
- if (count != 512)
- BX_PANIC( ("redolog : read HD with count not 512"));
-
- BX_DEBUG(("redolog : reading index %d, mapping to %d", extent_index, dtoh32(catalog[extent_index])));
-
- if (dtoh32(catalog[extent_index]) == REDOLOG_PAGE_NOT_ALLOCATED)
- {
- // page not allocated
- return 0;
- }
-
- bitmap_offset = (off_t)STANDARD_HEADER_SIZE + (dtoh32(header.specific.catalog) * sizeof(Bit32u));
- bitmap_offset += (off_t)512 * dtoh32(catalog[extent_index]) * (extent_blocs + bitmap_blocs);
- bloc_offset = bitmap_offset + ((off_t)512 * (bitmap_blocs + extent_offset));
-
- BX_DEBUG(("redolog : bitmap offset is %x", (Bit32u)bitmap_offset));
- BX_DEBUG(("redolog : bloc offset is %x", (Bit32u)bloc_offset));
-
-
- // FIXME if same extent_index as before we can skip bitmap read
-
- ::lseek(fd, bitmap_offset, SEEK_SET);
-
- if (::read(fd, bitmap, dtoh32(header.specific.bitmap)) != (ssize_t)dtoh32(header.specific.bitmap))
- {
- BX_PANIC(("redolog : failed to read bitmap for extent %d", extent_index));
- return 0;
- }
-
- if ( ((bitmap[extent_offset/8] >> (extent_offset%8)) & 0x01) == 0x00 )
- {
- BX_DEBUG(("read not in redolog"));
-
- // bitmap says bloc not in reloglog
- return 0;
- }
-
- ::lseek(fd, bloc_offset, SEEK_SET);
-
- return (::read(fd, buf, count));
-}
-
-ssize_t
-redolog_t::write (const void* buf, size_t count)
-{
- Bit32u i;
- off_t bloc_offset, bitmap_offset, catalog_offset;
- ssize_t written;
- bx_bool update_catalog = 0;
-
- if (count != 512)
- BX_PANIC( ("redolog : write HD with count not 512"));
-
- BX_DEBUG(("redolog : writing index %d, mapping to %d", extent_index, dtoh32(catalog[extent_index])));
- if (dtoh32(catalog[extent_index]) == REDOLOG_PAGE_NOT_ALLOCATED)
- {
- if(extent_next >= dtoh32(header.specific.catalog))
- {
- BX_PANIC(("redolog : can't allocate new extent... catalog is full"));
- return 0;
- }
-
- BX_DEBUG(("redolog : allocating new extent at %d", extent_next));
-
- // Extent not allocated, allocate new
- catalog[extent_index] = htod32(extent_next);
-
- extent_next += 1;
-
- char *zerobuffer = (char*)malloc(512);
- memset(zerobuffer, 0, 512);
-
- // Write bitmap
- bitmap_offset = (off_t)STANDARD_HEADER_SIZE + (dtoh32(header.specific.catalog) * sizeof(Bit32u));
- bitmap_offset += (off_t)512 * dtoh32(catalog[extent_index]) * (extent_blocs + bitmap_blocs);
- ::lseek(fd, bitmap_offset, SEEK_SET);
- for(i=0; i<bitmap_blocs; i++)
- {
- ::write(fd, zerobuffer, 512);
- }
- // Write extent
- for(i=0; i<extent_blocs; i++)
- {
- ::write(fd, zerobuffer, 512);
- }
-
- free(zerobuffer);
-
- update_catalog = 1;
- }
-
- bitmap_offset = (off_t)STANDARD_HEADER_SIZE + (dtoh32(header.specific.catalog) * sizeof(Bit32u));
- bitmap_offset += (off_t)512 * dtoh32(catalog[extent_index]) * (extent_blocs + bitmap_blocs);
- bloc_offset = bitmap_offset + ((off_t)512 * (bitmap_blocs + extent_offset));
-
- BX_DEBUG(("redolog : bitmap offset is %x", (Bit32u)bitmap_offset));
- BX_DEBUG(("redolog : bloc offset is %x", (Bit32u)bloc_offset));
-
- // Write bloc
- ::lseek(fd, bloc_offset, SEEK_SET);
- written = ::write(fd, buf, count);
-
- // Write bitmap
- // FIXME if same extent_index as before we can skip bitmap read
- ::lseek(fd, bitmap_offset, SEEK_SET);
- if (::read(fd, bitmap, dtoh32(header.specific.bitmap)) != (ssize_t)dtoh32(header.specific.bitmap))
- {
- BX_PANIC(("redolog : failed to read bitmap for extent %d", extent_index));
- return 0;
- }
-
- // If bloc does not belong to extent yet
- if ( ((bitmap[extent_offset/8] >> (extent_offset%8)) & 0x01) == 0x00 )
- {
- bitmap[extent_offset/8] |= 1 << (extent_offset%8);
- ::lseek(fd, bitmap_offset, SEEK_SET);
- ::write(fd, bitmap, dtoh32(header.specific.bitmap));
- }
-
- // Write catalog
- if (update_catalog)
- {
- // FIXME if mmap
- catalog_offset = (off_t)STANDARD_HEADER_SIZE + (extent_index * sizeof(Bit32u));
-
- BX_DEBUG(("redolog : writing catalog at offset %x", (Bit32u)catalog_offset));
-
- ::lseek(fd, catalog_offset, SEEK_SET);
- ::write(fd, &catalog[extent_index], sizeof(Bit32u));
- }
-
- return written;
-}
-
-
-/*** growing_image_t function definitions ***/
-
-growing_image_t::growing_image_t(Bit64u _size)
-{
- redolog = new redolog_t();
- size = _size;
-}
-
-int growing_image_t::open (const char* pathname)
-{
- int filedes = redolog->open(pathname,REDOLOG_SUBTYPE_GROWING,size);
- BX_INFO(("'growing' disk opened, growing file is '%s'", pathname));
- return filedes;
-}
-
-void growing_image_t::close ()
-{
- redolog->close();
-}
-
-off_t growing_image_t::lseek (off_t offset, int whence)
-{
- return redolog->lseek(offset, whence);
-}
-
-ssize_t growing_image_t::read (void* buf, size_t count)
-{
- memset(buf, 0, count);
- redolog->read((char*) buf, count);
- return count;
-}
-
-ssize_t growing_image_t::write (const void* buf, size_t count)
-{
- return redolog->write((char*) buf, count);
-}
-
-
-/*** undoable_image_t function definitions ***/
-
-undoable_image_t::undoable_image_t(Bit64u _size, const char* _redolog_name)
-{
- redolog = new redolog_t();
- ro_disk = new default_image_t();
- size = _size;
- redolog_name = NULL;
- if (_redolog_name != NULL) {
- if (strcmp(_redolog_name,"") != 0) {
- redolog_name = strdup(_redolog_name);
- }
- }
-}
-
-int undoable_image_t::open (const char* pathname)
-{
- char *logname=NULL;
-
- if (ro_disk->open(pathname, O_RDONLY)<0)
- return -1;
-
- // if redolog name was set
- if ( redolog_name != NULL) {
- if ( strcmp(redolog_name, "") != 0 ) {
- logname = (char*)malloc(strlen(redolog_name) + 1);
- strcpy (logname, redolog_name);
- }
- }
-
- // Otherwise we make up the redolog filename from the pathname
- if ( logname == NULL) {
- logname = (char*)malloc(strlen(pathname) + UNDOABLE_REDOLOG_EXTENSION_LENGTH + 1);
- sprintf (logname, "%s%s", pathname, UNDOABLE_REDOLOG_EXTENSION);
- }
-
- if (redolog->open(logname,REDOLOG_SUBTYPE_UNDOABLE,size) < 0)
- {
- if (redolog->create(logname, REDOLOG_SUBTYPE_UNDOABLE, size) < 0)
- {
- BX_PANIC(("Can't open or create redolog '%s'",logname));
- return -1;
- }
- }
-
- BX_INFO(("'undoable' disk opened: ro-file is '%s', redolog is '%s'", pathname, logname));
- free(logname);
-
- return 0;
-}
-
-void undoable_image_t::close ()
-{
- redolog->close();
- ro_disk->close();
-
- if (redolog_name!=NULL)
- free(redolog_name);
-}
-
-off_t undoable_image_t::lseek (off_t offset, int whence)
-{
- redolog->lseek(offset, whence);
- return ro_disk->lseek(offset, whence);
-}
-
-ssize_t undoable_image_t::read (void* buf, size_t count)
-{
- // This should be fixed if count != 512
- if ((size_t)redolog->read((char*) buf, count) != count)
- return ro_disk->read((char*) buf, count);
- else
- return count;
-}
-
-ssize_t undoable_image_t::write (const void* buf, size_t count)
-{
- return redolog->write((char*) buf, count);
-}
-
-
-/*** volatile_image_t function definitions ***/
-
-volatile_image_t::volatile_image_t(Bit64u _size, const char* _redolog_name)
-{
- redolog = new redolog_t();
- ro_disk = new default_image_t();
- size = _size;
- redolog_temp = NULL;
- redolog_name = NULL;
- if (_redolog_name != NULL) {
- if (strcmp(_redolog_name,"") != 0) {
- redolog_name = strdup(_redolog_name);
- }
- }
-}
-
-int volatile_image_t::open (const char* pathname)
-{
- int filedes;
- const char *logname=NULL;
-
- if (ro_disk->open(pathname, O_RDONLY)<0)
- return -1;
-
- // if redolog name was set
- if ( redolog_name != NULL) {
- if ( strcmp(redolog_name, "") != 0 ) {
- logname = redolog_name;
- }
- }
-
- // otherwise use pathname as template
- if (logname == NULL) {
- logname = pathname;
- }
-
- redolog_temp = (char*)malloc(strlen(logname) + VOLATILE_REDOLOG_EXTENSION_LENGTH + 1);
- sprintf (redolog_temp, "%s%s", logname, VOLATILE_REDOLOG_EXTENSION);
-
- filedes = mkstemp (redolog_temp);
-
- if (filedes < 0)
- {
- BX_PANIC(("Can't create volatile redolog '%s'", redolog_temp));
- return -1;
- }
- if (redolog->create(filedes, REDOLOG_SUBTYPE_VOLATILE, size) < 0)
- {
- BX_PANIC(("Can't create volatile redolog '%s'", redolog_temp));
- return -1;
- }
-
-#if (!defined(WIN32)) && !BX_WITH_MACOS
- // on unix it is legal to delete an open file
- unlink(redolog_temp);
-#endif
-
- BX_INFO(("'volatile' disk opened: ro-file is '%s', redolog is '%s'", pathname, redolog_temp));
-
- return 0;
-}
-
-void volatile_image_t::close ()
-{
- redolog->close();
- ro_disk->close();
-
-#if defined(WIN32) || BX_WITH_MACOS
- // on non-unix we have to wait till the file is closed to delete it
- unlink(redolog_temp);
-#endif
- if (redolog_temp!=NULL)
- free(redolog_temp);
-
- if (redolog_name!=NULL)
- free(redolog_name);
-}
-
-off_t volatile_image_t::lseek (off_t offset, int whence)
-{
- redolog->lseek(offset, whence);
- return ro_disk->lseek(offset, whence);
-}
-
-ssize_t volatile_image_t::read (void* buf, size_t count)
-{
- // This should be fixed if count != 512
- if ((size_t)redolog->read((char*) buf, count) != count)
- return ro_disk->read((char*) buf, count);
- else
- return count;
-}
-
-ssize_t volatile_image_t::write (const void* buf, size_t count)
-{
- return redolog->write((char*) buf, count);
-}
-
-#if BX_COMPRESSED_HD_SUPPORT
-
-/*** z_ro_image_t function definitions ***/
-
-z_ro_image_t::z_ro_image_t()
-{
- offset = (off_t)0;
-}
-
-int z_ro_image_t::open (const char* pathname)
-{
- fd = ::open(pathname, O_RDONLY
-#ifdef O_BINARY
- | O_BINARY
-#endif
- );
-
- if(fd < 0)
- {
- BX_PANIC(("Could not open '%s' file", pathname));
- return fd;
- }
-
- gzfile = gzdopen(fd, "rb");
-}
-
-void z_ro_image_t::close ()
-{
- if (fd > -1) {
- gzclose(gzfile);
- // ::close(fd);
- }
-}
-
-off_t z_ro_image_t::lseek (off_t _offset, int whence)
-{
- // Only SEEK_SET supported
- if (whence != SEEK_SET)
- {
- BX_PANIC(("lseek on compressed images : only SEEK_SET supported"));
- }
-
- // Seeking is expensive on compressed files, so we do it
- // only when necessary, at the latest moment
- offset = _offset;
-
- return offset;
-}
-
-ssize_t z_ro_image_t::read (void* buf, size_t count)
-{
- gzseek(gzfile, offset, SEEK_SET);
- return gzread(gzfile, buf, count);
-}
-
-ssize_t z_ro_image_t::write (const void* buf, size_t count)
-{
- BX_PANIC(("z_ro_image: write not supported"));
- return 0;
-}
-
-
-/*** z_undoable_image_t function definitions ***/
-
-z_undoable_image_t::z_undoable_image_t(Bit64u _size, const char* _redolog_name)
-{
- redolog = new redolog_t();
- ro_disk = new z_ro_image_t();
- size = _size;
-
- redolog_name = NULL;
- if (_redolog_name != NULL) {
- if (strcmp(_redolog_name,"") != 0) {
- redolog_name = strdup(_redolog_name);
- }
- }
-}
-
-int z_undoable_image_t::open (const char* pathname)
-{
- char *logname=NULL;
-
- if (ro_disk->open(pathname)<0)
- return -1;
-
- // If redolog name was set
- if ( redolog_name != NULL) {
- if ( strcmp(redolog_name, "") != 0) {
- logname = (char*)malloc(strlen(redolog_name) + 1);
- strcpy (logname, redolog_name);
- }
- }
-
- // Otherwise we make up the redolog filename from the pathname
- if ( logname == NULL) {
- logname = (char*)malloc(strlen(pathname) + UNDOABLE_REDOLOG_EXTENSION_LENGTH + 1);
- sprintf (logname, "%s%s", pathname, UNDOABLE_REDOLOG_EXTENSION);
- }
-
- if (redolog->open(logname,REDOLOG_SUBTYPE_UNDOABLE,size) < 0)
- {
- if (redolog->create(logname, REDOLOG_SUBTYPE_UNDOABLE, size) < 0)
- {
- BX_PANIC(("Can't open or create redolog '%s'",logname));
- return -1;
- }
- }
-
- BX_INFO(("'z-undoable' disk opened, z-ro-file is '%s', redolog is '%s'", pathname, logname));
- free(logname);
-
- return 0;
-}
-
-void z_undoable_image_t::close ()
-{
- redolog->close();
- ro_disk->close();
-
- if (redolog_name!=NULL)
- free(redolog_name);
-}
-
-off_t z_undoable_image_t::lseek (off_t offset, int whence)
-{
- redolog->lseek(offset, whence);
- return ro_disk->lseek(offset, whence);
-}
-
-ssize_t z_undoable_image_t::read (void* buf, size_t count)
-{
- // This should be fixed if count != 512
- if (redolog->read((char*) buf, count) != count)
- return ro_disk->read((char*) buf, count);
- else
- return count;
-}
-
-ssize_t z_undoable_image_t::write (const void* buf, size_t count)
-{
- return redolog->write((char*) buf, count);
-}
-
-
-/*** z_volatile_image_t function definitions ***/
-
-z_volatile_image_t::z_volatile_image_t(Bit64u _size, const char* _redolog_name)
-{
- redolog = new redolog_t();
- ro_disk = new z_ro_image_t();
- size = _size;
-
- redolog_temp = NULL;
- redolog_name = NULL;
- if (_redolog_name != NULL) {
- if (strcmp(_redolog_name,"") != 0) {
- redolog_name = strdup(_redolog_name);
- }
- }
-}
-
-int z_volatile_image_t::open (const char* pathname)
-{
- int filedes;
- const char *logname=NULL;
-
- if (ro_disk->open(pathname)<0)
- return -1;
-
- // if redolog name was set
- if ( redolog_name != NULL) {
- if ( strcmp(redolog_name, "") !=0 ) {
- logname = redolog_name;
- }
- }
-
- // otherwise use pathname as template
- if (logname == NULL) {
- logname = pathname;
- }
-
- redolog_temp = (char*)malloc(strlen(logname) + VOLATILE_REDOLOG_EXTENSION_LENGTH + 1);
- sprintf (redolog_temp, "%s%s", logname, VOLATILE_REDOLOG_EXTENSION);
-
- filedes = mkstemp (redolog_temp);
-
- if (filedes < 0)
- {
- BX_PANIC(("Can't create volatile redolog '%s'", redolog_temp));
- return -1;
- }
- if (redolog->create(filedes, REDOLOG_SUBTYPE_VOLATILE, size) < 0)
- {
- BX_PANIC(("Can't create volatile redolog '%s'", redolog_temp));
- return -1;
- }
-
-#if (!defined(WIN32)) && !BX_WITH_MACOS
- // on unix it is legal to delete an open file
- unlink(redolog_temp);
-#endif
-
- BX_INFO(("'z-volatile' disk opened: z-ro-file is '%s', redolog is '%s'", pathname, redolog_temp));
-
- return 0;
-}
-
-void z_volatile_image_t::close ()
-{
- redolog->close();
- ro_disk->close();
-
-#if defined(WIN32) || BX_WITH_MACOS
- // on non-unix we have to wait till the file is closed to delete it
- unlink(redolog_temp);
-#endif
-
- if (redolog_temp!=NULL)
- free(redolog_temp);
-
- if (redolog_name!=NULL)
- free(redolog_name);
-}
-
-off_t z_volatile_image_t::lseek (off_t offset, int whence)
-{
- redolog->lseek(offset, whence);
- return ro_disk->lseek(offset, whence);
-}
-
-ssize_t z_volatile_image_t::read (void* buf, size_t count)
-{
- // This should be fixed if count != 512
- if (redolog->read((char*) buf, count) != count)
- return ro_disk->read((char*) buf, count);
- else
- return count;
-}
-
-ssize_t z_volatile_image_t::write (const void* buf, size_t count)
-{
- return redolog->write((char*) buf, count);
-}
-
-
-#endif
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: harddrv.h,v 1.22.2.1 2004/02/06 22:14:36 danielg4 Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-// SPARSE IMAGES HEADER
-#define SPARSE_HEADER_MAGIC (0x02468ace)
-#define SPARSE_HEADER_VERSION 1
-#define SPARSE_HEADER_SIZE (256) // Plenty of room for later
-#define SPARSE_PAGE_NOT_ALLOCATED (0xffffffff)
-
- typedef struct
- {
- uint32 magic;
- uint32 version;
- uint32 pagesize;
- uint32 numpages;
-
- uint32 padding[60];
- } sparse_header_t;
-
-#define STANDARD_HEADER_MAGIC "Bochs Virtual HD Image"
-#define STANDARD_HEADER_VERSION (0x00010000)
-#define STANDARD_HEADER_SIZE (512)
-
-
- // WARNING : headers are kept in x86 (little) endianness
- typedef struct
- {
- Bit8u magic[32];
- Bit8u type[16];
- Bit8u subtype[16];
- Bit32u version;
- Bit32u header;
- } standard_header_t;
-
-#define REDOLOG_TYPE "Redolog"
-#define REDOLOG_SUBTYPE_UNDOABLE "Undoable"
-#define REDOLOG_SUBTYPE_VOLATILE "Volatile"
-#define REDOLOG_SUBTYPE_GROWING "Growing"
-// #define REDOLOG_SUBTYPE_Z_UNDOABLE "z-Undoable"
-// #define REDOLOG_SUBTYPE_Z_VOLATILE "z-Volatile"
-
-#define REDOLOG_PAGE_NOT_ALLOCATED (0xffffffff)
-
-#define UNDOABLE_REDOLOG_EXTENSION ".redolog"
-#define UNDOABLE_REDOLOG_EXTENSION_LENGTH (strlen(UNDOABLE_REDOLOG_EXTENSION))
-#define VOLATILE_REDOLOG_EXTENSION ".XXXXXX"
-#define VOLATILE_REDOLOG_EXTENSION_LENGTH (strlen(VOLATILE_REDOLOG_EXTENSION))
-
- typedef struct
- {
- // the fields in the header are kept in little endian
- Bit32u catalog; // #entries in the catalog
- Bit32u bitmap; // bitmap size in bytes
- Bit32u extent; // extent size in bytes
- Bit64u disk; // disk size in bytes
- } redolog_specific_header_t;
-
- typedef struct
- {
- standard_header_t standard;
- redolog_specific_header_t specific;
-
- Bit8u padding[STANDARD_HEADER_SIZE - (sizeof (standard_header_t) + sizeof (redolog_specific_header_t))];
- } redolog_header_t;
-
-// htod : convert host to disk (little) endianness
-// dtoh : convert disk (little) to host endianness
-#if defined (BX_LITTLE_ENDIAN)
-#define htod32(val) (val)
-#define dtoh32(val) (val)
-#define htod64(val) (val)
-#define dtoh64(val) (val)
-#else
-#define htod32(val) ( (((val)&0xff000000)>>24) | (((val)&0xff0000)>>8) | (((val)&0xff00)<<8) | (((val)&0xff)<<24) )
-#define dtoh32(val) htod32(val)
-#define htod64(val) ( (((val)&0xff00000000000000LL)>>56) | (((val)&0xff000000000000LL)>>40) | (((val)&0xff0000000000LL)>>24) | (((val)&0xff00000000LL)>>8) | (((val)&0xff000000LL)<<8) | (((val)&0xff0000LL)<<24) | (((val)&0xff00LL)<<40) | (((val)&0xffLL)<<56) )
-#define dtoh64(val) htod64(val)
-#endif
-
-#ifndef INCLUDE_ONLY_HD_HEADERS
-
-typedef enum _sense {
- SENSE_NONE = 0, SENSE_NOT_READY = 2, SENSE_ILLEGAL_REQUEST = 5,
- SENSE_UNIT_ATTENTION = 6
-} sense_t;
-
-typedef enum _asc {
- ASC_INV_FIELD_IN_CMD_PACKET = 0x24,
- ASC_MEDIUM_NOT_PRESENT = 0x3a,
- ASC_SAVING_PARAMETERS_NOT_SUPPORTED = 0x39,
- ASC_LOGICAL_BLOCK_OOR = 0x21
-} asc_t;
-
-class LOWLEVEL_CDROM;
-
-class device_image_t
-{
- public:
- // Open a image. Returns non-negative if successful.
- virtual int open (const char* pathname) = 0;
-
- // Close the image.
- virtual void close () = 0;
-
- // Position ourselves. Return the resulting offset from the
- // beginning of the file.
- virtual off_t lseek (off_t offset, int whence) = 0;
-
- // Read count bytes to the buffer buf. Return the number of
- // bytes read (count).
- virtual ssize_t read (void* buf, size_t count) = 0;
-
- // Write count bytes from buf. Return the number of bytes
- // written (count).
- virtual ssize_t write (const void* buf, size_t count) = 0;
-
- unsigned cylinders;
- unsigned heads;
- unsigned sectors;
-};
-
-// FLAT MODE
-class default_image_t : public device_image_t
-{
- public:
- // Open a image. Returns non-negative if successful.
- int open (const char* pathname);
-
- // Open an image with specific flags. Returns non-negative if successful.
- int open (const char* pathname, int flags);
-
- // Close the image.
- void close ();
-
- // Position ourselves. Return the resulting offset from the
- // beginning of the file.
- off_t lseek (off_t offset, int whence);
-
- // Read count bytes to the buffer buf. Return the number of
- // bytes read (count).
- ssize_t read (void* buf, size_t count);
-
- // Write count bytes from buf. Return the number of bytes
- // written (count).
- ssize_t write (const void* buf, size_t count);
-
- private:
- int fd;
-
-};
-
-// CONCAT MODE
-class concat_image_t : public device_image_t
-{
- public:
- // Default constructor
- concat_image_t();
-
- // Open a image. Returns non-negative if successful.
- int open (const char* pathname);
-
- // Close the image.
- void close ();
-
- // Position ourselves. Return the resulting offset from the
- // beginning of the file.
- off_t lseek (off_t offset, int whence);
-
- // Read count bytes to the buffer buf. Return the number of
- // bytes read (count).
- ssize_t read (void* buf, size_t count);
-
- // Write count bytes from buf. Return the number of bytes
- // written (count).
- ssize_t write (const void* buf, size_t count);
-
- private:
-#define BX_CONCAT_MAX_IMAGES 8
- int fd_table[BX_CONCAT_MAX_IMAGES];
- off_t start_offset_table[BX_CONCAT_MAX_IMAGES];
- off_t length_table[BX_CONCAT_MAX_IMAGES];
- void increment_string (char *str);
- int maxfd; // number of entries in tables that are valid
-
- // notice if anyone does sequential read or write without seek in between.
- // This can be supported pretty easily, but needs additional checks.
- // 0=something other than seek was last operation
- // 1=seek was last operation
- int seek_was_last_op;
-
- // the following variables tell which partial image file to use for
- // the next read and write.
- int index; // index into table
- int fd; // fd to use for reads and writes
- off_t thismin, thismax; // byte offset boundary of this image
-};
-
-// SPARSE MODE
-class sparse_image_t : public device_image_t
-{
-
-// Format of a sparse file:
-// 256 byte header, containing details such as page size and number of pages
-// Page indirection table, mapping virtual pages to physical pages within file
-// Physical pages till end of file
-
- public:
- // Default constructor
- sparse_image_t();
-
- // Open a image. Returns non-negative if successful.
- int open (const char* pathname);
-
- // Close the image.
- void close ();
-
- // Position ourselves. Return the resulting offset from the
- // beginning of the file.
- off_t lseek (off_t offset, int whence);
-
- // Read count bytes to the buffer buf. Return the number of
- // bytes read (count).
- ssize_t read (void* buf, size_t count);
-
- // Write count bytes from buf. Return the number of bytes
- // written (count).
- ssize_t write (const void* buf, size_t count);
-
- private:
- int fd;
-
-#ifdef _POSIX_MAPPED_FILES
- void * mmap_header;
- size_t mmap_length;
- size_t system_pagesize_mask;
-#endif
- uint32 * pagetable;
-
- // Header is written to disk in little-endian (x86) format
- // Thus needs to be converted on big-endian systems before read
- // The pagetable is also kept little endian
-
- sparse_header_t header;
-
- uint32 pagesize;
- int pagesize_shift;
- uint32 pagesize_mask;
-
- off_t data_start;
- off_t underlying_filesize;
-
- char * pathname;
-
- off_t position;
-
- uint32 position_virtual_page;
- uint32 position_physical_page;
- uint32 position_page_offset;
-
- off_t underlying_current_filepos;
-
- off_t total_size;
-
- void panic(const char * message);
- off_t
-#ifndef PARANOID
- sparse_image_t::
-#endif
- get_physical_offset();
- void
-#ifndef PARANOID
- sparse_image_t::
-#endif
- set_virtual_page(uint32 new_virtual_page);
- void read_header();
- ssize_t read_page_fragment(uint32 read_virtual_page, uint32 read_page_offset, size_t read_size, void * buf);
-
- sparse_image_t * parent_image;
-};
-
-#if EXTERNAL_DISK_SIMULATOR
-#include "external-disk-simulator.h"
-#endif
-
-#if DLL_HD_SUPPORT
-class dll_image_t : public device_image_t
-{
- public:
- // Open a image. Returns non-negative if successful.
- int open (const char* pathname);
-
- // Close the image.
- void close ();
-
- // Position ourselves. Return the resulting offset from the
- // beginning of the file.
- off_t lseek (off_t offset, int whence);
-
- // Read count bytes to the buffer buf. Return the number of
- // bytes read (count).
- ssize_t read (void* buf, size_t count);
-
- // Write count bytes from buf. Return the number of bytes
- // written (count).
- ssize_t write (const void* buf, size_t count);
-
- private:
- int vunit,vblk;
-
-};
-#endif
-
-// REDOLOG class
-class redolog_t
-{
- public:
- redolog_t();
- int make_header (const char* type, Bit64u size);
- int create (const char* filename, const char* type, Bit64u size);
- int create (int filedes, const char* type, Bit64u size);
- int open (const char* filename, const char* type, Bit64u size);
- void close ();
-
- off_t lseek (off_t offset, int whence);
- ssize_t read (void* buf, size_t count);
- ssize_t write (const void* buf, size_t count);
-
- private:
- void print_header();
- int fd;
- redolog_header_t header; // Header is kept in x86 (little) endianness
- Bit32u *catalog;
- Bit8u *bitmap;
- Bit32u extent_index;
- Bit32u extent_offset;
- Bit32u extent_next;
-
- Bit32u bitmap_blocs;
- Bit32u extent_blocs;
-};
-
-// GROWING MODE
-class growing_image_t : public device_image_t
-{
- public:
- // Contructor
- growing_image_t(Bit64u size);
-
- // Open a image. Returns non-negative if successful.
- int open (const char* pathname);
-
- // Close the image.
- void close ();
-
- // Position ourselves. Return the resulting offset from the
- // beginning of the file.
- off_t lseek (off_t offset, int whence);
-
- // Read count bytes to the buffer buf. Return the number of
- // bytes read (count).
- ssize_t read (void* buf, size_t count);
-
- // Write count bytes from buf. Return the number of bytes
- // written (count).
- ssize_t write (const void* buf, size_t count);
-
- private:
- redolog_t *redolog;
- Bit64u size;
-};
-
-// UNDOABLE MODE
-class undoable_image_t : public device_image_t
-{
- public:
- // Contructor
- undoable_image_t(Bit64u size, const char* redolog_name);
-
- // Open a image. Returns non-negative if successful.
- int open (const char* pathname);
-
- // Close the image.
- void close ();
-
- // Position ourselves. Return the resulting offset from the
- // beginning of the file.
- off_t lseek (off_t offset, int whence);
-
- // Read count bytes to the buffer buf. Return the number of
- // bytes read (count).
- ssize_t read (void* buf, size_t count);
-
- // Write count bytes from buf. Return the number of bytes
- // written (count).
- ssize_t write (const void* buf, size_t count);
-
- private:
- redolog_t *redolog; // Redolog instance
- default_image_t *ro_disk; // Read-only flat disk instance
- Bit64u size;
- char *redolog_name; // Redolog name
-};
-
-
-// VOLATILE MODE
-class volatile_image_t : public device_image_t
-{
- public:
- // Contructor
- volatile_image_t(Bit64u size, const char* redolog_name);
-
- // Open a image. Returns non-negative if successful.
- int open (const char* pathname);
-
- // Close the image.
- void close ();
-
- // Position ourselves. Return the resulting offset from the
- // beginning of the file.
- off_t lseek (off_t offset, int whence);
-
- // Read count bytes to the buffer buf. Return the number of
- // bytes read (count).
- ssize_t read (void* buf, size_t count);
-
- // Write count bytes from buf. Return the number of bytes
- // written (count).
- ssize_t write (const void* buf, size_t count);
-
- private:
- redolog_t *redolog; // Redolog instance
- default_image_t *ro_disk; // Read-only flat disk instance
- Bit64u size;
- char *redolog_name; // Redolog name
- char *redolog_temp; // Redolog temporary file name
-};
-
-
-#if BX_COMPRESSED_HD_SUPPORT
-
-#include <zlib.h>
-
-
-// Default compressed READ-ONLY image class
-class z_ro_image_t : public device_image_t
-{
- public:
- // Contructor
- z_ro_image_t();
-
- // Open a image. Returns non-negative if successful.
- int open (const char* pathname);
-
- // Close the image.
- void close ();
-
- // Position ourselves. Return the resulting offset from the
- // beginning of the file.
- off_t lseek (off_t offset, int whence);
-
- // Read count bytes to the buffer buf. Return the number of
- // bytes read (count).
- ssize_t read (void* buf, size_t count);
-
- // Write count bytes from buf. Return the number of bytes
- // written (count).
- ssize_t write (const void* buf, size_t count);
-
- private:
- off_t offset;
- int fd;
- gzFile gzfile;
-
-};
-
-// Z-UNDOABLE MODE
-class z_undoable_image_t : public device_image_t
-{
- public:
- // Contructor
- z_undoable_image_t(Bit64u size, const char* redolog_name);
-
- // Open a image. Returns non-negative if successful.
- int open (const char* pathname);
-
- // Close the image.
- void close ();
-
- // Position ourselves. Return the resulting offset from the
- // beginning of the file.
- off_t lseek (off_t offset, int whence);
-
- // Read count bytes to the buffer buf. Return the number of
- // bytes read (count).
- ssize_t read (void* buf, size_t count);
-
- // Write count bytes from buf. Return the number of bytes
- // written (count).
- ssize_t write (const void* buf, size_t count);
-
- private:
- redolog_t *redolog; // Redolog instance
- z_ro_image_t *ro_disk; // Read-only compressed flat disk instance
- Bit64u size;
- char *redolog_name; // Redolog name
-};
-
-// Z-VOLATILE MODE
-class z_volatile_image_t : public device_image_t
-{
- public:
- // Contructor
- z_volatile_image_t(Bit64u size, const char* redolog_name);
-
- // Open a image. Returns non-negative if successful.
- int open (const char* pathname);
-
- // Close the image.
- void close ();
-
- // Position ourselves. Return the resulting offset from the
- // beginning of the file.
- off_t lseek (off_t offset, int whence);
-
- // Read count bytes to the buffer buf. Return the number of
- // bytes read (count).
- ssize_t read (void* buf, size_t count);
-
- // Write count bytes from buf. Return the number of bytes
- // written (count).
- ssize_t write (const void* buf, size_t count);
-
- private:
- redolog_t *redolog; // Redolog instance
- z_ro_image_t *ro_disk; // Read-only compressed flat disk instance
- Bit64u size;
- char *redolog_name; // Redolog name
- char *redolog_temp; // Redolog temporary file name
-};
-
-#endif
-
-
-typedef struct {
- struct {
- bx_bool busy;
- bx_bool drive_ready;
- bx_bool write_fault;
- bx_bool seek_complete;
- bx_bool drq;
- bx_bool corrected_data;
- bx_bool index_pulse;
- unsigned index_pulse_count;
- bx_bool err;
- } status;
- Bit8u error_register;
- Bit8u head_no;
- union {
- Bit8u sector_count;
- struct {
-#ifdef BX_LITTLE_ENDIAN
- unsigned c_d : 1;
- unsigned i_o : 1;
- unsigned rel : 1;
- unsigned tag : 5;
-#else /* BX_BIG_ENDIAN */
- unsigned tag : 5;
- unsigned rel : 1;
- unsigned i_o : 1;
- unsigned c_d : 1;
-#endif
- } interrupt_reason;
- };
- Bit8u sector_no;
- union {
- Bit16u cylinder_no;
- Bit16u byte_count;
- };
- Bit8u buffer[2048];
- Bit32u buffer_index;
- Bit32u drq_index;
- Bit8u current_command;
- Bit8u sectors_per_block;
- Bit8u lba_mode;
- struct {
- bx_bool reset; // 0=normal, 1=reset controller
- bx_bool disable_irq; // 0=allow irq, 1=disable irq
- } control;
- Bit8u reset_in_progress;
- Bit8u features;
- } controller_t;
-
-struct sense_info_t {
- sense_t sense_key;
- struct {
- Bit8u arr[4];
- } information;
- struct {
- Bit8u arr[4];
- } specific_inf;
- struct {
- Bit8u arr[3];
- } key_spec;
- Bit8u fruc;
- Bit8u asc;
- Bit8u ascq;
-};
-
-struct error_recovery_t {
- unsigned char data[8];
-
- error_recovery_t ();
-};
-
-uint16 read_16bit(const uint8* buf) BX_CPP_AttrRegparmN(1);
-uint32 read_32bit(const uint8* buf) BX_CPP_AttrRegparmN(1);
-
-
-#ifdef LOWLEVEL_CDROM
-# include "cdrom.h"
-#endif
-
-
-struct cdrom_t
-{
- bx_bool ready;
- bx_bool locked;
-#ifdef LOWLEVEL_CDROM
- LOWLEVEL_CDROM* cd;
-#endif
- uint32 capacity;
- int next_lba;
- int remaining_blocks;
- struct currentStruct {
- error_recovery_t error_recovery;
- } current;
-};
-
-struct atapi_t
-{
- uint8 command;
- int drq_bytes;
- int total_bytes_remaining;
-};
-
-#if BX_USE_HD_SMF
-# define BX_HD_SMF static
-# define BX_HD_THIS theHardDrive->
-#else
-# define BX_HD_SMF
-# define BX_HD_THIS this->
-#endif
-
-typedef enum {
- IDE_NONE, IDE_DISK, IDE_CDROM
-} device_type_t;
-
-class bx_hard_drive_c : public bx_hard_drive_stub_c {
-public:
-
- bx_hard_drive_c(void);
- virtual ~bx_hard_drive_c(void);
- virtual void close_harddrive(void);
- virtual void init();
- virtual void reset(unsigned type);
- virtual Bit32u get_device_handle(Bit8u channel, Bit8u device);
- virtual Bit32u get_first_cd_handle(void);
- virtual unsigned get_cd_media_status(Bit32u handle);
- virtual unsigned set_cd_media_status(Bit32u handle, unsigned status);
-
- virtual Bit32u virt_read_handler(Bit32u address, unsigned io_len) {
- return read_handler (this, address, io_len);
- }
- virtual void virt_write_handler(Bit32u address,
- Bit32u value, unsigned io_len)
- {
- write_handler(this, address, value, io_len);
- }
-#if !BX_USE_HD_SMF
- Bit32u read(Bit32u address, unsigned io_len);
- void write(Bit32u address, Bit32u value, unsigned io_len);
-#endif
-
- static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len);
- static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len);
-
-private:
-
- BX_HD_SMF bx_bool calculate_logical_address(Bit8u channel, off_t *sector) BX_CPP_AttrRegparmN(2);
- BX_HD_SMF void increment_address(Bit8u channel) BX_CPP_AttrRegparmN(1);
- BX_HD_SMF void identify_drive(Bit8u channel);
- BX_HD_SMF void identify_ATAPI_drive(Bit8u channel);
- BX_HD_SMF void command_aborted(Bit8u channel, unsigned command);
-
- BX_HD_SMF void init_send_atapi_command(Bit8u channel, Bit8u command, int req_length, int alloc_length, bool lazy = false) BX_CPP_AttrRegparmN(3);
- BX_HD_SMF void ready_to_send_atapi(Bit8u channel) BX_CPP_AttrRegparmN(1);
- BX_HD_SMF void raise_interrupt(Bit8u channel) BX_CPP_AttrRegparmN(1);
- BX_HD_SMF void atapi_cmd_error(Bit8u channel, sense_t sense_key, asc_t asc);
- BX_HD_SMF void init_mode_sense_single(Bit8u channel, const void* src, int size);
- BX_HD_SMF void atapi_cmd_nop(Bit8u channel) BX_CPP_AttrRegparmN(1);
-
- // FIXME:
- // For each ATA channel we should have one controller struct
- // and an array of two drive structs
- struct channel_t {
- struct drive_t {
- device_image_t* hard_drive;
- device_type_t device_type;
- // 512 byte buffer for ID drive command
- // These words are stored in native word endian format, as
- // they are fetched and returned via a return(), so
- // there's no need to keep them in x86 endian format.
- Bit16u id_drive[256];
-
- controller_t controller;
- cdrom_t cdrom;
- sense_info_t sense;
- atapi_t atapi;
-
- Bit8u model_no[41];
- } drives[2];
- unsigned drive_select;
-
- Bit16u ioaddr1;
- Bit16u ioaddr2;
- Bit8u irq;
-
- } channels[BX_MAX_ATA_CHANNEL];
-
-#if BX_PDC20230C_VLBIDE_SUPPORT
-// pdc20630c is only available for 1st ata channel
- struct pdc20630c_t {
- bx_bool prog_mode;
- Bit8u prog_count;
- Bit32u p1f3_value;
- Bit32u p1f4_value;
- } pdc20230c;
-#endif
-
- };
-#endif // INCLUDE_ONLY_SPARSE_HEADER
-
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: ioapic.cc,v 1.11 2002/11/19 05:47:45 bdenney Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-#include <stdio.h>
-#include "bochs.h"
-#if BX_SUPPORT_APIC
-
-class bx_ioapic_c bx_ioapic;
-#define LOG_THIS bx_ioapic.
-
-void
-bx_io_redirect_entry_t::parse_value ()
-{
- dest = (value >> 56) & 0xff;
- masked = (value >> 16) & 1;
- trig_mode = (value >> 15) & 1;
- remote_irr = (value >> 14) & 1;
- polarity = (value >> 13) & 1;
- //delivery_status = (value >> 12) & 1;
- delivery_status = 0; // always say the message has gone through
- dest_mode = (value >> 11) & 1;
- delivery_mode = (value >> 8) & 7;
- vector = (value >> 0) & 0xff;
-}
-
-void
-bx_io_redirect_entry_t::sprintf_self (char *buf)
-{
- sprintf (buf, "dest=%02x, masked=%d, trig_mode=%d, remote_irr=%d, polarity=%d, delivery_status=%d, dest_mode=%d, delivery_mode=%d, vector=%02x", dest, masked, trig_mode, remote_irr, polarity, delivery_status, dest_mode, delivery_mode, vector);
-}
-
-bx_ioapic_c::bx_ioapic_c ()
- : bx_generic_apic_c ()
-{
- put("IOAP");
- settype(IOAPICLOG);
-}
-
-bx_ioapic_c::~bx_ioapic_c () {
-}
-
-void
-bx_ioapic_c::init ()
-{
- bx_generic_apic_c::init ();
- BX_DEBUG(("initializing I/O APIC"));
- base_addr = 0xfec00000;
- ioregsel = 0;
- // all interrupts masked
- for (int i=0; i<BX_IOAPIC_NUM_PINS; i++) {
- ioredtbl[i].set_even_word (0x00010000);
- ioredtbl[i].set_odd_word (0x00000000);
- }
- irr = 0;
-}
-
-void
-bx_ioapic_c::reset (unsigned type)
-{
-}
-
-void
-bx_ioapic_c::read_aligned(Bit32u address, Bit32u *data, unsigned len)
-{
- BX_DEBUG( ("I/O APIC read_aligned addr=%08x, len=%d", address, len));
- BX_ASSERT (len == 4);
- address &= 0xff;
- if (address == 0x00) {
- // select register
- *data = ioregsel;
- return;
- } else if (address != 0x10) {
- BX_PANIC(("IOAPIC: read from unsupported address"));
- }
- // only reached when reading data register
- switch (ioregsel) {
- case 0x00: // APIC ID
- *data = ((id & 0xf) << 24);
- return;
- case 0x01: // version
- *data = (((BX_IOAPIC_NUM_PINS-1) & 0xff) << 16)
- | (BX_IOAPIC_VERSION_ID & 0x0f);
- return;
- case 0x02:
- BX_INFO(("IOAPIC: arbitration ID unsupported, returned 0"));
- *data = 0;
- return;
- default:
- int index = (ioregsel - 0x10) >> 1;
- if (index >= 0 && index < BX_IOAPIC_NUM_PINS) {
- bx_io_redirect_entry_t *entry = ioredtbl + index;
- *data = (ioregsel&1) ? entry->get_odd_word() : entry->get_even_word ();
- return;
- }
- BX_PANIC(("IOAPIC: IOREGSEL points to undefined register %02x", ioregsel));
- }
-}
-
-void
-bx_ioapic_c::write(Bit32u address, Bit32u *value, unsigned len)
-{
- BX_DEBUG(("IOAPIC: write addr=%08x, data=%08x, len=%d", address, *value, len));
- address &= 0xff;
- if (address == 0x00) {
- ioregsel = *value;
- return;
- } else if (address != 0x10) {
- BX_PANIC(("IOAPIC: write to unsupported address"));
- }
- // only reached when writing data register
- switch (ioregsel) {
- case 0x00: // set APIC ID
- {
- Bit8u newid = (*value >> 24) & 0xf;
- BX_INFO(("IOAPIC: setting id to 0x%x", newid));
- set_id (newid);
- return;
- }
- case 0x01: // version
- case 0x02: // arbitration id
- BX_INFO(("IOAPIC: could not write, IOREGSEL=0x%02x", ioregsel));
- return;
- default:
- int index = (ioregsel - 0x10) >> 1;
- if (index >= 0 && index < BX_IOAPIC_NUM_PINS) {
- bx_io_redirect_entry_t *entry = ioredtbl + index;
- if (ioregsel&1)
- entry->set_odd_word (*value);
- else
- entry->set_even_word (*value);
- char buf[1024];
- entry->sprintf_self (buf);
- BX_DEBUG(("IOAPIC: now entry[%d] is %s", index, buf));
- service_ioapic ();
- return;
- }
- BX_PANIC(("IOAPIC: IOREGSEL points to undefined register %02x", ioregsel));
- }
-}
-
-void bx_ioapic_c::trigger_irq (unsigned vector, unsigned from)
-{
- BX_DEBUG(("IOAPIC: received interrupt %d", vector));
- if (vector >= 0 && vector < BX_IOAPIC_NUM_PINS) {
- Bit32u bit = 1<<vector;
- if ((irr & bit) == 0) {
- irr |= bit;
- service_ioapic ();
- }
- } else BX_PANIC(("IOAPIC: vector %d out of range", vector));
-}
-
-void bx_ioapic_c::untrigger_irq (unsigned num, unsigned from)
-{
- BX_DEBUG(("IOAPIC: interrupt %d went away", num));
-}
-
-void bx_ioapic_c::service_ioapic ()
-{
- // look in IRR and deliver any interrupts that are not masked.
- BX_DEBUG(("IOAPIC: servicing"));
- for (unsigned bit=0; bit < BX_IOAPIC_NUM_PINS; bit++) {
- if (irr & (1<<bit)) {
- bx_io_redirect_entry_t *entry = ioredtbl + bit;
- if (!entry->masked) {
- // clear irr bit and deliver
- bx_bool done = deliver (entry->dest, entry->dest_mode, entry->delivery_mode, entry->vector, entry->polarity, entry->trig_mode);
- if (done) irr &= ~(1<<bit);
- }
- }
- }
-}
-
-#endif /* if BX_SUPPORT_APIC */
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: ioapic.h,v 1.5 2002/10/25 11:44:40 bdenney Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-extern class bx_ioapic_c bx_ioapic;
-
-#define BX_IOAPIC_VERSION_ID 0x00170011 // same version as 82093 IOAPIC
-#define BX_IOAPIC_NUM_PINS 0x18
-
-class bx_io_redirect_entry_t {
- Bit64u value;
-public:
- Bit32u get_even_word () { return value & 0xffffffff; }
- Bit32u get_odd_word () { return (value>>32) & 0xffffffff; }
- void set_even_word (Bit32u even) {
- // keep high 32 bits of value, replace low 32
- value = ((value >> 32) << 32) | (even & 0xffffffff);
- parse_value ();
- }
- void set_odd_word (Bit32u odd) {
- // keep low 32 bits of value, replace high 32
- value = (((Bit64u)odd & 0xffffffff) << 32) | (value & 0xffffffff);
- parse_value ();
- }
- void parse_value ();
- // parse_value sets the value and all the fields below. Do not change
- // these fields except by calling parse_value.
- Bit8u dest, masked, trig_mode, remote_irr, polarity, delivery_status, dest_mode, delivery_mode, vector;
- void sprintf_self (char *buf);
-};
-
-class bx_ioapic_c : public bx_generic_apic_c {
- Bit32u ioregsel; // selects between various registers
- // interrupt request bitmask, not visible from the outside. Bits in the
- // irr are set when trigger_irq is called, and cleared when the interrupt
- // is delivered to the processor. If an interrupt is masked, the irr
- // will still be set but delivery will not occur until it is unmasked.
- // It's not clear if this is how the real device works.
- Bit32u irr;
-public:
- bx_io_redirect_entry_t ioredtbl[BX_IOAPIC_NUM_PINS]; // table of redirections
- bx_ioapic_c ();
- ~bx_ioapic_c ();
- virtual void init ();
- virtual void reset (unsigned type);
- virtual void read_aligned(Bit32u address, Bit32u *data, unsigned len);
- virtual void write(Bit32u address, Bit32u *value, unsigned len);
- void trigger_irq (unsigned num, unsigned from);
- void untrigger_irq (unsigned num, unsigned from);
- void service_ioapic ();
- virtual bx_bool match_logical_addr (Bit8u address) { return false; }
- virtual bx_bool is_local_apic () { return false; }
- virtual bx_apic_type_t get_type () { return APIC_TYPE_IOAPIC; }
-};
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: iodebug.cc,v 1.15 2002/11/19 05:47:45 bdenney Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-#include "bochs.h"
-#if BX_IODEBUG_SUPPORT
-
-
-
-bx_iodebug_c bx_iodebug;
-bx_iodebug_c *bx_iodebug_ptr;
-
- struct bx_iodebug_s_type {
- bx_bool enabled;
- unsigned int register_select;
- Bit32u registers[2];
- Bit32u monitored_mem_areas_start[BX_IODEBUG_MAX_AREAS];
- Bit32u monitored_mem_areas_end[BX_IODEBUG_MAX_AREAS];
- } bx_iodebug_s;
-
-
-
-
-// Constructor
-bx_iodebug_c::bx_iodebug_c( void )
-{
- put("IODEBUG");
- settype(IODEBUGLOG);
-
-}
-
-
-
-
-
-// Destructor
-bx_iodebug_c::~bx_iodebug_c( void )
-{
-}
-
-
-
-
-
-void bx_iodebug_c::init(void)
-{
- int i;
-
- DEV_register_ioread_handler(this, read_handler, 0x8A00,"BOCHS IODEBUG", 7);
- DEV_register_iowrite_handler(this, write_handler, 0x8A00,"BOCHS IODEBUG", 7);
- DEV_register_iowrite_handler(this, write_handler, 0x8A01,"BOCHS IODEBUG", 7);
-// fprintf( stderr, "IODEBUG initialized\n");
-
- bx_iodebug_s.enabled = 0;
- bx_iodebug_s.register_select = 0;
- for(i=0;i<BX_IODEBUG_MAX_AREAS;i++) {
- bx_iodebug_s.monitored_mem_areas_start[i] = 0;
- bx_iodebug_s.monitored_mem_areas_end[i] = 0;
- }
-}
-
-void bx_iodebug_c::reset(unsigned type)
-{
-}
-
-
-Bit32u bx_iodebug_c::read_handler(void *this_ptr, Bit32u addr, unsigned io_len)
-{
- bx_iodebug_ptr = (bx_iodebug_c *) this_ptr;
- return( bx_iodebug_ptr->read(addr, io_len) );
-}
-
-
-
-
-
-
-Bit32u bx_iodebug_c::read( Bit32u addr, unsigned io_len )
-{
-
- if(bx_iodebug_s.enabled) return(0x8A00);
- return(0);
-}
-
-
-
-
-
-
-
-
-
-
-void bx_iodebug_c::write_handler(void *this_ptr, Bit32u addr, Bit32u dvalue, unsigned io_len)
-{
- bx_iodebug_c *class_ptr = (bx_iodebug_c *) this_ptr;
- class_ptr->write( addr, dvalue, io_len );
-}
-
-
-
-
-
-
-void bx_iodebug_c::write( Bit32u addr, Bit32u dvalue, unsigned int io_len )
-{
-
-
-// fprintf(stderr, "IODEBUG addr: %4x\tdvalue: %8x\tio_len: %8x\n", (unsigned int)addr, (unsigned int)dvalue, io_len);
-
- if( addr == 0x8A01 && io_len == 2 )
- {
- bx_iodebug_s.registers[bx_iodebug_s.register_select] =
- (bx_iodebug_s.registers[bx_iodebug_s.register_select] << 16) +
- (dvalue & 0x0000FFFF );
- }
-
- if( (addr != 0x8A00) || (io_len != 2) ) return;
-
- if( !bx_iodebug_s.enabled )
- {
- if( dvalue == 0x8A00 )
- {
- bx_iodebug_s.enabled = 1;
-// fprintf(stderr, "IODEBUG enabled\n");
- bx_iodebug_s.registers[0] = 0;
- bx_iodebug_s.registers[1] = 0;
- }
- return;
- }
-
- switch( dvalue )
- {
- case( 0x8A01 ):
- bx_iodebug_s.register_select = 0;
-// fprintf( stderr, "IODEBUG register 0 selected\n");
- break;
-
- case( 0x8A02 ):
- bx_iodebug_s.register_select = 1;
-// fprintf( stderr, "IODEBUG register 1 selected\n");
- break;
-
- case( 0x8A80 ):
- bx_iodebug_s.register_select = 0;
- bx_iodebug_c::add_range(
- bx_iodebug_s.registers[0],
- bx_iodebug_s.registers[1]);
- bx_iodebug_s.registers[0] = 0;
- bx_iodebug_s.registers[1] = 0;
- break;
-
-#if BX_DEBUGGER
- case( 0x8AE0 ):
- fprintf( stderr, "request return to dbg prompt received, 0x8AE0 command (iodebug)\n");
- bx_guard.interrupt_requested=1;
- break;
-
- case( 0x8AE2):
- fprintf( stderr, "request made by the guest os to disable tracing, iodebug port 0x8A00->0x8AE2\n");
- BX_CPU(dbg_cpu)->trace = 0;
- break;
-
- case( 0x8AE3 ):
- fprintf( stderr, "request made by the guest os to enable tracing, iodebug port 0x8A00->0x8AE3\n");
- BX_CPU(dbg_cpu)->trace = 1;
- break;
-
- case( 0x8AE4 ):
- fprintf( stderr, "request made by the guest os to disable register tracing, iodebug port 0x8A00->0x8AE4\n");
- BX_CPU(dbg_cpu)->trace_reg = 0;
- break;
-
- case( 0x8AE5 ):
- fprintf( stderr, "request made by the guest os to enable register tracing, iodebug port 0x8A00->0x8AE5\n");
- BX_CPU(dbg_cpu)->trace_reg = 1;
- break;
-
-#endif
-
- case( 0x8AFF ):
- bx_iodebug_s.enabled = 0;
-// fprintf( stderr, "IODEBUG device deactivated\n");
-// break;
-
-// default:
-// fprintf(stderr,"IODEBUG unsupported register code\n");
- }
-}
-
-
-
-
-
-
-
-
-// Static function
-void bx_iodebug_c::mem_write( BX_CPU_C *cpu, Bit32u addr, unsigned len, void *data)
-{
- Bit32u data32;
- Bit16u data16;
- Bit8u data8;
-
- unsigned int area;
- if( !bx_iodebug_s.enabled ) return;
-
- area = bx_iodebug_c::range_test( addr, len );
- // Device is enabled, testing address ranges
- if( area )
- {
- area--;
-#if BX_DEBUGGER
- fprintf( stdout, "%s @ eip: %08X wrote at monitored memory location %8X\n", cpu->name, cpu->get_EIP(), addr);
- bx_guard.interrupt_requested=1;
-#else
- fprintf( stderr,
- "IODEBUG write to monitored memory area: %2i\tby EIP:\t\t%08X\n\trange start: \t\t%08X\trange end:\t%08X\n\taddress accessed:\t%08X\tdata written:\t",
- area,
- cpu->get_EIP(),
- bx_iodebug_s.monitored_mem_areas_start[area],
- bx_iodebug_s.monitored_mem_areas_end[area],
- (unsigned int)addr);
-
- data32 = * (Bit32u *)data;
- data16 = (Bit16u)data32;
- data8 = (Bit8u)data32;
-
- switch(len)
- {
- case(1):
- fprintf(stderr,"%02X\n", (unsigned int)data8);
- break;
-
- case(2):
- fprintf(stderr,"%04X\n", (unsigned int)data16);
- break;
-
- case(4):
- fprintf(stderr,"%08X\n", (unsigned int)data32);
- break;
-
- default:
- fprintf(stderr, "unsupported write size\n");
- }
-#endif
- }
-}
-
-
-
-
-
-
-
-
-void bx_iodebug_c::mem_read( BX_CPU_C *cpu, Bit32u addr, unsigned len, void *data)
-{
- Bit32u data32;
- Bit16u data16;
- Bit8u data8;
-
- unsigned int area;
- if( !bx_iodebug_s.enabled ) return;
-
- area = bx_iodebug_c::range_test( addr, len );
- // Device is enabled, testing address ranges
- if( area )
- {
- area--;
-#if BX_DEBUGGER
- fprintf( stdout, "%s @ eip: %8X wrote at monitored memory location %8X\n", cpu->name, cpu->get_EIP(), addr);
- bx_guard.interrupt_requested=1;
-#else
- fprintf( stderr,
- "IODEBUG read to monitored memory area: %2i\tby EIP:\t\t%08X\n\trange start: \t\t%08X\trange end:\t%08X\n\taddress accessed:\t%08X\tdata written:\t",
- area,
- cpu->get_EIP(),
- bx_iodebug_s.monitored_mem_areas_start[area],
- bx_iodebug_s.monitored_mem_areas_end[area],
- (unsigned int)addr);
- data32 = * (Bit32u *)data;
- data16 = (Bit16u)data32;
- data8 = (Bit8u)data32;
-
- switch(len)
- {
- case(1):
- fprintf(stderr,"%02X\n", (unsigned int)data8);
- break;
-
- case(2):
- fprintf(stderr,"%04X\n", (unsigned int)data16);
- break;
-
- case(4):
- fprintf(stderr,"%08X\n", (unsigned int)data32);
- break;
-
- default:
- fprintf(stderr, "unsupported write size\n");
- }
-#endif
- }
-}
-
-
-
-
-
-
-
-unsigned int bx_iodebug_c::range_test( Bit32u addr, unsigned int len )
-{
- unsigned int i;
-
- for(i=0;i<BX_IODEBUG_MAX_AREAS;i++)
- {
- if( (bx_iodebug_s.monitored_mem_areas_start[i]!=0) ||
- (bx_iodebug_s.monitored_mem_areas_end[i]!=0) )
- {
- if( (Bit32u)(addr+len-1) < bx_iodebug_s.monitored_mem_areas_start[i] )
- continue;
- if( addr < bx_iodebug_s.monitored_mem_areas_end[i] )
- {
- return(++i);
- }
- }
- }
- return(0);
-}
-
-
-
-
-
-
-void bx_iodebug_c::add_range( Bit32u addr_start, Bit32u addr_end )
-{
- unsigned int i;
- for(i=0;i<BX_IODEBUG_MAX_AREAS;i++)
- {
- if( !bx_iodebug_s.monitored_mem_areas_start[i] &&
- !bx_iodebug_s.monitored_mem_areas_end[i] )
- {
- bx_iodebug_s.monitored_mem_areas_start[i] = addr_start;
- bx_iodebug_s.monitored_mem_areas_end[i] = addr_end;
-// fprintf(stderr, "IODEBUG added range successfully in slot: %i\n",i);
- return;
- }
- }
-// fprintf(stderr, "IODEBUG unable to register memory range, all slots taken\n");
-}
-#endif /* if BX_IODEBUG_SUPPORT */
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: iodebug.h,v 1.7 2002/10/26 03:53:22 bdenney Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-#ifndef _BX_IODEBUG_H
-#define _BX_IODEBUG_H
-
-#include "config.h"
-
-#define BX_IODEBUG_THIS this->
-
-#define BX_IODEBUG_MAX_AREAS 30
-
-class bx_iodebug_c : public bx_devmodel_c
-{
-public:
- bx_iodebug_c( void );
- ~bx_iodebug_c( void );
- virtual void init(void);
- virtual void reset (unsigned type);
- static void mem_write( BX_CPU_C *cpu, Bit32u addr, unsigned len, void *data);
- static void mem_read( BX_CPU_C *cpu, Bit32u addr, unsigned len, void *data);
-
-private:
- static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len);
- static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len);
- Bit32u read(Bit32u addr, unsigned int io_len);
- void write(Bit32u addr, Bit32u dvalue, unsigned int io_len);
- static unsigned int range_test(Bit32u addr, unsigned int len);
- static void add_range( Bit32u addr_start, Bit32u addr_end);
-
-};
-
-extern bx_iodebug_c bx_iodebug;
-#endif
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: iodev.h,v 1.37 2003/08/04 16:03:09 akrisak Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-
-/* maximum number of emulated devices allowed. floppy, vga, etc...
- you can increase this to anything below 256 since an 8-bit handle
- is used for each device */
-#define BX_MAX_IO_DEVICES 30
-
-/* the last device in the array is the "default" I/O device */
-#define BX_DEFAULT_IO_DEVICE (BX_MAX_IO_DEVICES-1)
-
-/* number of IRQ lines supported. In an ISA PC there are two
- PIC chips cascaded together. each has 8 IRQ lines, so there
- should be 16 IRQ's total */
-#define BX_MAX_IRQS 16
-#define BX_NO_IRQ -1
-
-
-class bx_pit_c;
-class bx_keyb_c;
-class bx_ioapic_c;
-class bx_g2h_c;
-#if BX_IODEBUG_SUPPORT
-class bx_iodebug_c;
-#endif
-
-
-
-typedef Bit32u (*bx_read_handler_t)(void *, Bit32u, unsigned);
-typedef void (*bx_write_handler_t)(void *, Bit32u, Bit32u, unsigned);
-
-
-#if BX_USE_DEV_SMF
-# define BX_DEV_SMF static
-# define BX_DEV_THIS bx_devices.
-#else
-# define BX_DEV_SMF
-# define BX_DEV_THIS this->
-#endif
-
-//////////////////////////////////////////////////////////////////////
-// bx_devmodel_c declaration
-//////////////////////////////////////////////////////////////////////
-
-// This class defines virtual methods that are common to all devices.
-// Child classes do not need to implement all of them, because in this
-// definition they are defined as empty, as opposed to being pure
-// virtual (= 0).
-class BOCHSAPI bx_devmodel_c : public logfunctions {
- public:
- virtual ~bx_devmodel_c () {}
- virtual void init_mem(BX_MEM_C *) {}
- virtual void init(void) {}
- virtual void reset(unsigned type) {}
- virtual void device_load_state () {}
- virtual void device_save_state () {}
-};
-
-//////////////////////////////////////////////////////////////////////
-// declare stubs for devices
-//////////////////////////////////////////////////////////////////////
-
-#define STUBFUNC(dev,method) \
- pluginlog->panic("%s called in %s stub. you must not have loaded the %s plugin", #dev, #method, #dev )
-
-class BOCHSAPI bx_keyb_stub_c : public bx_devmodel_c {
- public:
- virtual ~bx_keyb_stub_c () {}
- // stubs for bx_keyb_c methods
- virtual void mouse_motion(int delta_x, int delta_y, unsigned button_state) {
- STUBFUNC(keyboard, mouse_motion);
- }
- virtual void gen_scancode(Bit32u key) {
- STUBFUNC(keyboard, gen_scancode);
- }
- virtual void paste_bytes(Bit8u *data, Bit32s length) {
- STUBFUNC(keyboard, paste_bytes);
- }
- virtual void paste_delay_changed () {
- STUBFUNC(keyboard, paste_delay_changed);
- }
- virtual void mouse_enabled_changed(bool enabled) {
- STUBFUNC(keyboard, mouse_enabled_changed);
- }
-};
-
-class BOCHSAPI bx_hard_drive_stub_c : public bx_devmodel_c {
- public:
- virtual void close_harddrive(void) {
- STUBFUNC(HD, close_harddrive);
- }
- virtual void init() {
- STUBFUNC(HD, init);
- }
- virtual void reset(unsigned type) {
- STUBFUNC(HD, reset);
- }
- virtual Bit32u get_device_handle(Bit8u channel, Bit8u device) {
- STUBFUNC(HD, get_device_handle); return 0;
- }
- virtual Bit32u get_first_cd_handle(void) {
- STUBFUNC(HD, get_first_cd_handle); return 0;
- }
- virtual unsigned get_cd_media_status(Bit32u handle) {
- STUBFUNC(HD, get_cd_media_status); return 0;
- }
- virtual unsigned set_cd_media_status(Bit32u handle, unsigned status) {
- STUBFUNC(HD, set_cd_media_status); return 0;
- }
- virtual Bit32u virt_read_handler(Bit32u address, unsigned io_len)
- {
- STUBFUNC(HD, virt_read_handler); return 0;
- }
- virtual void virt_write_handler(Bit32u address,
- Bit32u value, unsigned io_len)
- {
- STUBFUNC(HD, virt_write_handler);
- }
-};
-
-class BOCHSAPI bx_floppy_stub_c : public bx_devmodel_c {
- public:
- virtual unsigned get_media_status(unsigned drive) {
- STUBFUNC(floppy, get_media_status); return 0;
- }
- virtual unsigned set_media_status(unsigned drive, unsigned status) {
- STUBFUNC(floppy, set_media_status); return 0;
- }
-};
-
-class BOCHSAPI bx_cmos_stub_c : public bx_devmodel_c {
- public:
- virtual Bit32u get_reg(unsigned reg) {
- STUBFUNC(cmos, get_reg); return 0;
- }
- virtual void set_reg(unsigned reg, Bit32u val) {
- STUBFUNC(cmos, set_reg);
- }
- virtual time_t get_timeval() {
- // STUBFUNC(cmos, get_timeval);
- return 0;
- }
- virtual void checksum_cmos(void) {
- STUBFUNC(cmos, checksum);
- }
-};
-
-class BOCHSAPI bx_dma_stub_c : public bx_devmodel_c {
- public:
- virtual unsigned registerDMA8Channel(
- unsigned channel,
- void (* dmaRead)(Bit8u *data_byte),
- void (* dmaWrite)(Bit8u *data_byte),
- const char *name
- ) {
- STUBFUNC(dma, registerDMA8Channel); return 0;
- }
- virtual unsigned registerDMA16Channel(
- unsigned channel,
- void (* dmaRead)(Bit16u *data_word),
- void (* dmaWrite)(Bit16u *data_word),
- const char *name
- ) {
- STUBFUNC(dma, registerDMA16Channel); return 0;
- }
- virtual unsigned unregisterDMAChannel(unsigned channel) {
- STUBFUNC(dma, unregisterDMAChannel); return 0;
- }
- virtual unsigned get_TC(void) {
- STUBFUNC(dma, get_TC); return 0;
- }
- virtual void set_DRQ(unsigned channel, bx_bool val) {
- STUBFUNC(dma, set_DRQ);
- }
- virtual void raise_HLDA(void) {
- STUBFUNC(dma, raise_HLDA);
- }
-};
-
-class BOCHSAPI bx_pic_stub_c : public bx_devmodel_c {
- public:
- virtual void raise_irq(unsigned irq_no) {
- STUBFUNC(pic, raise_irq);
- }
- virtual void lower_irq(unsigned irq_no) {
- STUBFUNC(pic, lower_irq);
- }
- virtual Bit8u IAC(void) {
- STUBFUNC(pic, IAC); return 0;
- }
- virtual void show_pic_state(void) {
- STUBFUNC(pic, show_pic_state);
- }
-};
-
-class BOCHSAPI bx_vga_stub_c : public bx_devmodel_c {
- public:
- virtual void redraw_area(unsigned x0, unsigned y0,
- unsigned width, unsigned height) {
- STUBFUNC(vga, redraw_area);
- }
- virtual Bit8u mem_read(Bit32u addr) {
- STUBFUNC(vga, mem_read); return 0;
- }
- virtual void mem_write(Bit32u addr, Bit8u value) {
- STUBFUNC(vga, mem_write);
- }
- virtual void get_text_snapshot(Bit8u **text_snapshot,
- unsigned *txHeight, unsigned *txWidth) {
- STUBFUNC(vga, get_text_snapshot);
- }
- virtual void trigger_timer(void *this_ptr) {
- STUBFUNC(vga, trigger_timer);
- }
- virtual void set_update_interval (unsigned interval) {
- STUBFUNC(vga, set_update_interval);
- }
- virtual Bit8u get_actl_palette_idx(Bit8u index) {
- return 0;
- }
-};
-
-class BOCHSAPI bx_pci_stub_c : public bx_devmodel_c {
- public:
- virtual bx_bool register_pci_handlers(void *this_ptr,
- Bit32u (*bx_pci_read_handler)(void *, Bit8u, unsigned),
- void(*bx_pci_write_handler)(void *, Bit8u, Bit32u, unsigned),
- Bit8u devfunc, const char *name) {
- STUBFUNC(pci, register_pci_handlers); return 0;
- }
- virtual Bit8u rd_memType (Bit32u addr) {
- return 0;
- }
- virtual Bit8u wr_memType (Bit32u addr) {
- return 0;
- }
- virtual void print_i440fx_state(void) {}
-};
-
-class BOCHSAPI bx_ne2k_stub_c : public bx_devmodel_c {
- public:
- virtual void print_info(FILE *file, int page, int reg, int nodups) {}
-};
-
-class BOCHSAPI bx_devices_c : public logfunctions {
-public:
- bx_devices_c(void);
- ~bx_devices_c(void);
- // Register I/O addresses and IRQ lines. Initialize any internal
- // structures. init() is called only once, even if the simulator
- // reboots or is restarted.
- void init(BX_MEM_C *);
- // Enter reset state in response to a reset condition.
- // The types of reset conditions are defined in bochs.h:
- // power-on, hardware, or software.
- void reset(unsigned type);
- BX_MEM_C *mem; // address space associated with these devices
- bx_bool register_io_read_handler(void *this_ptr, bx_read_handler_t f, Bit32u addr, const char *name, Bit8u mask );
- bx_bool register_io_write_handler(void *this_ptr, bx_write_handler_t f, Bit32u addr, const char *name, Bit8u mask );
- bx_bool register_default_io_read_handler(void *this_ptr, bx_read_handler_t f, const char *name, Bit8u mask );
- bx_bool register_default_io_write_handler(void *this_ptr, bx_write_handler_t f, const char *name, Bit8u mask );
- bx_bool register_irq(unsigned irq, const char *name);
- bx_bool unregister_irq(unsigned irq, const char *name);
- void iodev_init(void);
- Bit32u inp(Bit16u addr, unsigned io_len) BX_CPP_AttrRegparmN(2);
- void outp(Bit16u addr, Bit32u value, unsigned io_len) BX_CPP_AttrRegparmN(3);
-
- static void timer_handler(void *);
- void timer(void);
-
- bx_devmodel_c *pluginBiosDevice;
- bx_ioapic_c *ioapic;
- bx_pci_stub_c *pluginPciBridge;
- bx_devmodel_c *pluginPci2IsaBridge;
- bx_devmodel_c *pluginPciVgaAdapter;
- bx_devmodel_c *pluginPciUSBAdapter;
- bx_pit_c *pit;
- bx_keyb_stub_c *pluginKeyboard;
- bx_dma_stub_c *pluginDmaDevice;
- bx_floppy_stub_c *pluginFloppyDevice;
- bx_cmos_stub_c *pluginCmosDevice;
- bx_devmodel_c *pluginSerialDevice;
- bx_devmodel_c *pluginParallelDevice;
- bx_devmodel_c *pluginUnmapped;
- bx_vga_stub_c *pluginVgaDevice;
- bx_pic_stub_c *pluginPicDevice;
- bx_hard_drive_stub_c *pluginHardDrive;
- bx_devmodel_c *pluginSB16Device;
- bx_ne2k_stub_c *pluginNE2kDevice;
- bx_g2h_c *g2h;
- bx_devmodel_c *pluginExtFpuIrq;
- bx_devmodel_c *pluginGameport;
-#if BX_IODEBUG_SUPPORT
- bx_iodebug_c *iodebug;
-#endif
-
- // stub classes that the pointers (above) can point to until a plugin is
- // loaded
- bx_cmos_stub_c stubCmos;
- bx_keyb_stub_c stubKeyboard;
- bx_hard_drive_stub_c stubHardDrive;
- bx_dma_stub_c stubDma;
- bx_pic_stub_c stubPic;
- bx_floppy_stub_c stubFloppy;
- bx_vga_stub_c stubVga;
- bx_pci_stub_c stubPci;
- bx_ne2k_stub_c stubNE2k;
-
- // Some info to pass to devices which can handled bulk IO. This allows
- // the interface to remain the same for IO devices which can't handle
- // bulk IO. We should probably implement special INPBulk() and OUTBulk()
- // functions which stick these values in the bx_devices_c class, and
- // then call the normal functions rather than having gross globals
- // variables.
- Bit32u bulkIOHostAddr;
- unsigned bulkIOQuantumsRequested;
- unsigned bulkIOQuantumsTransferred;
-
-private:
-
- Bit8u read_handler_id[0x10000]; // 64K
- struct {
- bx_read_handler_t funct;
- void *this_ptr;
- const char *handler_name; // name of device
- Bit8u mask; // io_len mask
- } io_read_handler[BX_MAX_IO_DEVICES];
- unsigned num_read_handles;
-
- Bit8u write_handler_id[0x10000]; // 64K
- struct {
- bx_write_handler_t funct;
- void *this_ptr;
- const char *handler_name; // name of device
- Bit8u mask; // io_len mask
- } io_write_handler[BX_MAX_IO_DEVICES];
- unsigned num_write_handles;
-
- // more for informative purposes, the names of the devices which
- // are use each of the IRQ 0..15 lines are stored here
- const char *irq_handler_name[BX_MAX_IRQS];
-
- static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len);
- static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len);
- BX_DEV_SMF Bit32u port92_read(Bit32u address, unsigned io_len);
- BX_DEV_SMF void port92_write(Bit32u address, Bit32u value, unsigned io_len);
-
- static Bit32u default_read_handler(void *this_ptr, Bit32u address, unsigned io_len);
- static void default_write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len);
-
- int timer_handle;
- bx_bool is_serial_enabled ();
- bx_bool is_usb_enabled ();
- bx_bool is_parallel_enabled ();
- };
-
-
-
-#if BX_PCI_SUPPORT
-#include "iodev/pci.h"
-#include "iodev/pci2isa.h"
-#if BX_PCI_VGA_SUPPORT
-#include "iodev/pcivga.h"
-#endif
-#if BX_PCI_USB_SUPPORT
-#include "iodev/pciusb.h"
-#endif
-#endif
-#include "iodev/vga.h"
-#if BX_SUPPORT_APIC
-# include "iodev/ioapic.h"
-#endif
-#include "iodev/biosdev.h"
-#include "iodev/cmos.h"
-#include "iodev/dma.h"
-#include "iodev/floppy.h"
-#include "iodev/harddrv.h"
-#if BX_IODEBUG_SUPPORT
-# include "iodev/iodebug.h"
-#endif
-#include "iodev/keyboard.h"
-#include "iodev/parallel.h"
-#include "iodev/pic.h"
-#include "iodev/pit.h"
-#include "iodev/pit_wrap.h"
-#include "iodev/virt_timer.h"
-#include "iodev/serial.h"
-#if BX_SUPPORT_SB16
-# include "iodev/sb16.h"
-#endif
-#include "iodev/unmapped.h"
-#include "iodev/eth.h"
-#include "iodev/ne2k.h"
-#include "iodev/guest2host.h"
-#include "iodev/slowdown_timer.h"
-#include "iodev/extfpuirq.h"
-#include "iodev/gameport.h"
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: keyboard.cc,v 1.82 2003/11/11 18:18:36 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-// Now features proper implementation of keyboard opcodes 0xF4 to 0xF6
-// Silently ignores PS/2 keyboard extensions (0xF7 to 0xFD)
-// Explicit panic on resend (0xFE)
-//
-// Emmanuel Marty <core@ggi-project.org>
-
-// NB: now the PS/2 mouse support is in, outb changes meaning
-// in conjunction with auxb
-// auxb == 0 && outb == 0 => both buffers empty (nothing to read)
-// auxb == 0 && outb == 1 => keyboard controller output buffer full
-// auxb == 1 && outb == 0 => not used
-// auxb == 1 && outb == 1 => mouse output buffer full.
-// (das)
-
-// Notes from Christophe Bothamy <cbbochs@free.fr>
-//
-// This file includes code from Ludovic Lange (http://ludovic.lange.free.fr)
-// Implementation of 3 scancodes sets mf1,mf2,mf3 with or without translation.
-// Default is mf2 with translation
-// Ability to switch between scancodes sets
-// Ability to turn translation on or off
-
-// Define BX_PLUGGABLE in files that can be compiled into plugins. For
-// platforms that require a special tag on exported symbols, BX_PLUGGABLE
-// is used to know when we are exporting symbols and when we are importing.
-#define BX_PLUGGABLE
-
-#include "bochs.h"
-#include <math.h>
-#include "scancodes.h"
-
-#define LOG_THIS theKeyboard->
-#define VERBOSE_KBD_DEBUG 0
-
-
-bx_keyb_c *theKeyboard = NULL;
-
- int
-libkeyboard_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[])
-{
- // Create one instance of the keyboard device object.
- theKeyboard = new bx_keyb_c ();
- // Before this plugin was loaded, pluginKeyboard pointed to a stub.
- // Now make it point to the real thing.
- bx_devices.pluginKeyboard = theKeyboard;
- // Register this device.
- BX_REGISTER_DEVICE_DEVMODEL (plugin, type, theKeyboard, BX_PLUGIN_KEYBOARD);
- return(0); // Success
-}
-
- void
-libkeyboard_LTX_plugin_fini(void)
-{
- BX_INFO (("keyboard plugin_fini"));
-}
-
-bx_keyb_c::bx_keyb_c(void)
-{
- // constructor
- put("KBD");
- settype(KBDLOG);
-}
-
-bx_keyb_c::~bx_keyb_c(void)
-{
- // destructor
- BX_DEBUG(("Exit."));
-}
-
-
-// flush internal buffer and reset keyboard settings to power-up condition
- void
-bx_keyb_c::resetinternals(bx_bool powerup)
-{
- Bit32u i;
-
- BX_KEY_THIS s.kbd_internal_buffer.num_elements = 0;
- for (i=0; i<BX_KBD_ELEMENTS; i++)
- BX_KEY_THIS s.kbd_internal_buffer.buffer[i] = 0;
- BX_KEY_THIS s.kbd_internal_buffer.head = 0;
-
- BX_KEY_THIS s.kbd_internal_buffer.expecting_typematic = 0;
-
- // Default scancode set is mf2 with translation
- BX_KEY_THIS s.kbd_controller.expecting_scancodes_set = 0;
- BX_KEY_THIS s.kbd_controller.current_scancodes_set = 1;
- BX_KEY_THIS s.kbd_controller.scancodes_translate = 1;
-
- if (powerup) {
- BX_KEY_THIS s.kbd_internal_buffer.expecting_led_write = 0;
- BX_KEY_THIS s.kbd_internal_buffer.delay = 1; // 500 mS
- BX_KEY_THIS s.kbd_internal_buffer.repeat_rate = 0x0b; // 10.9 chars/sec
- }
-}
-
-
-
- void
-bx_keyb_c::init(void)
-{
- BX_DEBUG(("Init $Id: keyboard.cc,v 1.82 2003/11/11 18:18:36 vruppert Exp $"));
- Bit32u i;
-
- DEV_register_irq(1, "8042 Keyboard controller");
- DEV_register_irq(12, "8042 Keyboard controller (PS/2 mouse)");
-
- DEV_register_ioread_handler(this, read_handler,
- 0x0060, "8042 Keyboard controller", 1);
- DEV_register_ioread_handler(this, read_handler,
- 0x0064, "8042 Keyboard controller", 1);
- DEV_register_iowrite_handler(this, write_handler,
- 0x0060, "8042 Keyboard controller", 1);
- DEV_register_iowrite_handler(this, write_handler,
- 0x0064, "8042 Keyboard controller", 1);
- BX_KEY_THIS timer_handle = bx_pc_system.register_timer( this, timer_handler,
- bx_options.Okeyboard_serial_delay->get(), 1, 1,
- "8042 Keyboard controller");
-
- resetinternals(1);
-
- BX_KEY_THIS s.kbd_internal_buffer.led_status = 0;
- BX_KEY_THIS s.kbd_internal_buffer.scanning_enabled = 1;
-
- BX_KEY_THIS s.mouse_internal_buffer.num_elements = 0;
- for (i=0; i<BX_MOUSE_BUFF_SIZE; i++)
- BX_KEY_THIS s.mouse_internal_buffer.buffer[i] = 0;
- BX_KEY_THIS s.mouse_internal_buffer.head = 0;
-
- // BX_INFO(("kbd: %04d outb 0 auxb 0",__LINE__)); // das
- BX_KEY_THIS s.kbd_controller.pare = 0;
- BX_KEY_THIS s.kbd_controller.tim = 0;
- BX_KEY_THIS s.kbd_controller.auxb = 0;
- BX_KEY_THIS s.kbd_controller.keyl = 1;
- BX_KEY_THIS s.kbd_controller.c_d = 1;
- BX_KEY_THIS s.kbd_controller.sysf = 0;
- BX_KEY_THIS s.kbd_controller.inpb = 0;
- BX_KEY_THIS s.kbd_controller.outb = 0;
-
- BX_KEY_THIS s.kbd_controller.kbd_clock_enabled = 1;
- BX_KEY_THIS s.kbd_controller.aux_clock_enabled = 0;
- BX_KEY_THIS s.kbd_controller.allow_irq1 = 1;
- BX_KEY_THIS s.kbd_controller.allow_irq12 = 1;
- BX_KEY_THIS s.kbd_controller.kbd_output_buffer = 0;
- BX_KEY_THIS s.kbd_controller.aux_output_buffer = 0;
- BX_KEY_THIS s.kbd_controller.last_comm = 0;
- BX_KEY_THIS s.kbd_controller.expecting_port60h = 0;
- BX_KEY_THIS s.kbd_controller.irq1_requested = 0;
- BX_KEY_THIS s.kbd_controller.irq12_requested = 0;
- BX_KEY_THIS s.kbd_controller.expecting_mouse_parameter = 0;
-
-//BX_DEBUG(( "# Okeyboard_serial_delay is %u usec",
-// (unsigned) bx_options.Okeyboard_serial_delay->get ()));
- BX_KEY_THIS s.kbd_controller.timer_pending = 0;
-
- // Mouse initialization stuff
- BX_KEY_THIS s.mouse.sample_rate = 100; // reports per second
- BX_KEY_THIS s.mouse.resolution_cpmm = 4; // 4 counts per millimeter
- BX_KEY_THIS s.mouse.scaling = 1; /* 1:1 (default) */
- BX_KEY_THIS s.mouse.mode = MOUSE_MODE_RESET;
- BX_KEY_THIS s.mouse.enable = 0;
- BX_KEY_THIS s.mouse.delayed_dx = 0;
- BX_KEY_THIS s.mouse.delayed_dy = 0;
-
- for (i=0; i<BX_KBD_CONTROLLER_QSIZE; i++)
- BX_KEY_THIS s.controller_Q[i] = 0;
- BX_KEY_THIS s.controller_Qsize = 0;
- BX_KEY_THIS s.controller_Qsource = 0;
-
- // clear paste buffer
- BX_KEY_THIS pastebuf = NULL;
- BX_KEY_THIS pastebuf_len = 0;
- BX_KEY_THIS pastebuf_ptr = 0;
- BX_KEY_THIS paste_delay_changed ();
- BX_KEY_THIS stop_paste = 0;
-
- // mouse port installed on system board
- DEV_cmos_set_reg(0x14, DEV_cmos_get_reg(0x14) | 0x04);
-
-#if BX_WITH_WX
- static bx_bool first_time = 1;
- if (first_time) {
- first_time = 0;
- // register shadow params (Experimental, not a complete list by far)
- bx_list_c *list = new bx_list_c (BXP_KBD_PARAMETERS, "Keyboard State", "", 20);
- list->add (new bx_shadow_bool_c (BXP_KBD_IRQ1_REQ,
- "Keyboard IRQ1 requested: ", "",
- &BX_KEY_THIS s.kbd_controller.irq1_requested));
- list->add (new bx_shadow_bool_c (BXP_KBD_IRQ12_REQ,
- "Keyboard IRQ12 requested: ", "",
- &BX_KEY_THIS s.kbd_controller.irq12_requested));
- list->add (new bx_shadow_num_c (BXP_KBD_TIMER_PENDING,
- "Keyboard timer pending: ", "",
- &BX_KEY_THIS s.kbd_controller.timer_pending));
- list->add (new bx_shadow_bool_c (BXP_KBD_PARE,
- "Keyboard PARE", "",
- &BX_KEY_THIS s.kbd_controller.pare));
- list->add (new bx_shadow_bool_c (BXP_KBD_TIM,
- "Keyboard TIM", "",
- &BX_KEY_THIS s.kbd_controller.tim));
- list->add (new bx_shadow_bool_c (BXP_KBD_AUXB,
- "Keyboard AUXB", "",
- &BX_KEY_THIS s.kbd_controller.auxb));
- list->add (new bx_shadow_bool_c (BXP_KBD_KEYL,
- "Keyboard KEYL", "",
- &BX_KEY_THIS s.kbd_controller.keyl));
- list->add (new bx_shadow_bool_c (BXP_KBD_C_D,
- "Keyboard C_D", "",
- &BX_KEY_THIS s.kbd_controller.c_d));
- list->add (new bx_shadow_bool_c (BXP_KBD_SYSF,
- "Keyboard SYSF", "",
- &BX_KEY_THIS s.kbd_controller.sysf));
- list->add (new bx_shadow_bool_c (BXP_KBD_INPB,
- "Keyboard INPB", "",
- &BX_KEY_THIS s.kbd_controller.inpb));
- list->add (new bx_shadow_bool_c (BXP_KBD_OUTB,
- "Keyboard OUTB", "",
- &BX_KEY_THIS s.kbd_controller.outb));
- }
-#endif
-}
-
- void
-bx_keyb_c::reset(unsigned type)
-{
- if (BX_KEY_THIS pastebuf != NULL) {
- BX_KEY_THIS stop_paste = 1;
- }
-}
-
- void
-bx_keyb_c::paste_delay_changed()
-{
- BX_KEY_THIS pastedelay = bx_options.Okeyboard_paste_delay->get()/BX_IODEV_HANDLER_PERIOD;
- BX_INFO(("will paste characters every %d keyboard ticks",BX_KEY_THIS pastedelay));
-}
-
- // static IO port read callback handler
- // redirects to non-static class handler to avoid virtual functions
-
-// read function - the big picture:
-// if address == data port then
-// if byte for mouse then return it
-// else if byte for keyboard then return it
-// else address== status port
-// assemble the status bits and return them.
-//
- Bit32u
-bx_keyb_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len)
-{
-#if !BX_USE_KEY_SMF
- bx_keyb_c *class_ptr = (bx_keyb_c *) this_ptr;
-
- return( class_ptr->read(address, io_len) );
-}
-
-
- Bit32u
-bx_keyb_c::read(Bit32u address, unsigned io_len)
-{
-#else
- UNUSED(this_ptr);
-#endif // !BX_USE_KEY_SMF
-
-//BX_DEBUG(( "read from port 0x%04x", (unsigned) address));
-
- if (address == 0x60) { /* output buffer */
- Bit8u val;
- if (BX_KEY_THIS s.kbd_controller.auxb) { /* mouse byte available */
- val = BX_KEY_THIS s.kbd_controller.aux_output_buffer;
- BX_KEY_THIS s.kbd_controller.aux_output_buffer = 0;
- // BX_INFO(("kbd: %04d outb 0 auxb 0",__LINE__)); // das
- BX_KEY_THIS s.kbd_controller.outb = 0;
- BX_KEY_THIS s.kbd_controller.auxb = 0;
- BX_KEY_THIS s.kbd_controller.irq12_requested = 0;
-
- if (BX_KEY_THIS s.controller_Qsize) {
- unsigned i;
- BX_KEY_THIS s.kbd_controller.aux_output_buffer = BX_KEY_THIS s.controller_Q[0];
- // BX_INFO(("kbd: %04d outb 1 auxb 1",__LINE__)); // das
- BX_KEY_THIS s.kbd_controller.outb = 1;
- BX_KEY_THIS s.kbd_controller.auxb = 1;
- if (BX_KEY_THIS s.kbd_controller.allow_irq12)
- BX_KEY_THIS s.kbd_controller.irq12_requested = 1;
- for (i=0; i<BX_KEY_THIS s.controller_Qsize-1; i++) {
- // move Q elements towards head of queue by one
- BX_KEY_THIS s.controller_Q[i] = BX_KEY_THIS s.controller_Q[i+1];
- }
- BX_KEY_THIS s.controller_Qsize--;
- }
-
-//BX_DEBUG(("mouse: ___io_read aux = 0x%02x", (unsigned) val));
-
- DEV_pic_lower_irq(12);
- activate_timer();
- BX_DEBUG(("READ(%02x) (from mouse) = %02x", (unsigned) address,
- (unsigned) val));
- return val;
- }
- else if (BX_KEY_THIS s.kbd_controller.outb) { /* kbd byte available */
- val = BX_KEY_THIS s.kbd_controller.kbd_output_buffer;
- // BX_INFO(("kbd: %04d outb 0 auxb 0",__LINE__)); // das
- BX_KEY_THIS s.kbd_controller.outb = 0;
- BX_KEY_THIS s.kbd_controller.auxb = 0;
- BX_KEY_THIS s.kbd_controller.irq1_requested = 0;
-//BX_DEBUG(( "___io_read kbd"));
-
- if (BX_KEY_THIS s.controller_Qsize) {
- unsigned i;
- BX_KEY_THIS s.kbd_controller.aux_output_buffer = BX_KEY_THIS s.controller_Q[0];
- // BX_INFO(("kbd: %04d outb 1 auxb 1",__LINE__)); // das
- BX_KEY_THIS s.kbd_controller.outb = 1;
- BX_KEY_THIS s.kbd_controller.auxb = 1;
- if (BX_KEY_THIS s.kbd_controller.allow_irq1)
- BX_KEY_THIS s.kbd_controller.irq1_requested = 1;
- for (i=0; i<BX_KEY_THIS s.controller_Qsize-1; i++) {
- // move Q elements towards head of queue by one
- BX_KEY_THIS s.controller_Q[i] = BX_KEY_THIS s.controller_Q[i+1];
- }
- BX_DEBUG(("s.controller_Qsize: %02X",BX_KEY_THIS s.controller_Qsize));
- BX_KEY_THIS s.controller_Qsize--;
- }
-
- DEV_pic_lower_irq(1);
- activate_timer();
- BX_DEBUG(("READ(%02x) = %02x", (unsigned) address,
- (unsigned) val));
- return val;
- }
- else {
- BX_DEBUG(("num_elements = %d", BX_KEY_THIS s.kbd_internal_buffer.num_elements));
- BX_DEBUG(("read from port 60h with outb empty"));
-// val = BX_KEY_THIS s.kbd_controller.kbd_output_buffer;
- return BX_KEY_THIS s.kbd_controller.kbd_output_buffer;
- }
- }
-
-#if BX_CPU_LEVEL >= 2
- else if (address == 0x64) { /* status register */
-
- return (BX_KEY_THIS s.kbd_controller.pare << 7) |
- (BX_KEY_THIS s.kbd_controller.tim << 6) |
- (BX_KEY_THIS s.kbd_controller.auxb << 5) |
- (BX_KEY_THIS s.kbd_controller.keyl << 4) |
- (BX_KEY_THIS s.kbd_controller.c_d << 3) |
- (BX_KEY_THIS s.kbd_controller.sysf << 2) |
- (BX_KEY_THIS s.kbd_controller.inpb << 1) |
- BX_KEY_THIS s.kbd_controller.outb;
- }
-
-#else /* BX_CPU_LEVEL > 0 */
- /* XT MODE, System 8255 Mode Register */
- else if (address == 0x64) { /* status register */
- BX_DEBUG(("IO read from port 64h, system 8255 mode register"));
- return BX_KEY_THIS s.kbd_controller.outb;
- }
-#endif /* BX_CPU_LEVEL > 0 */
-
- BX_PANIC(("unknown address in io read to keyboard port %x",
- (unsigned) address));
- return 0; /* keep compiler happy */
-}
-
-
- // static IO port write callback handler
- // redirects to non-static class handler to avoid virtual functions
-
- void
-bx_keyb_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len)
-{
-#if !BX_USE_KEY_SMF
- bx_keyb_c *class_ptr = (bx_keyb_c *) this_ptr;
-
- class_ptr->write(address, value, io_len);
-}
-
- void
-bx_keyb_c::write( Bit32u address, Bit32u value, unsigned io_len)
-{
-#else
- UNUSED(this_ptr);
-#endif // !BX_USE_KEY_SMF
- Bit8u command_byte;
- static int kbd_initialized=0;
-
- BX_DEBUG(("keyboard: 8-bit write to %04x = %02x", (unsigned)address, (unsigned)value));
-
- switch (address) {
- case 0x60: // input buffer
- // if expecting data byte from command last sent to port 64h
- if (BX_KEY_THIS s.kbd_controller.expecting_port60h) {
- BX_KEY_THIS s.kbd_controller.expecting_port60h = 0;
- // data byte written last to 0x60
- BX_KEY_THIS s.kbd_controller.c_d = 0;
- if (BX_KEY_THIS s.kbd_controller.inpb) {
- BX_PANIC(("write to port 60h, not ready for write"));
- }
- switch (BX_KEY_THIS s.kbd_controller.last_comm) {
- case 0x60: // write command byte
- {
- bx_bool scan_convert, disable_keyboard,
- disable_aux;
-
- scan_convert = (value >> 6) & 0x01;
- disable_aux = (value >> 5) & 0x01;
- disable_keyboard = (value >> 4) & 0x01;
- BX_KEY_THIS s.kbd_controller.sysf = (value >> 2) & 0x01;
- BX_KEY_THIS s.kbd_controller.allow_irq1 = (value >> 0) & 0x01;
- BX_KEY_THIS s.kbd_controller.allow_irq12 = (value >> 1) & 0x01;
- set_kbd_clock_enable(!disable_keyboard);
- set_aux_clock_enable(!disable_aux);
- if (BX_KEY_THIS s.kbd_controller.allow_irq12 && BX_KEY_THIS s.kbd_controller.auxb)
- BX_KEY_THIS s.kbd_controller.irq12_requested = 1;
- else if (BX_KEY_THIS s.kbd_controller.allow_irq1 && BX_KEY_THIS s.kbd_controller.outb)
- BX_KEY_THIS s.kbd_controller.irq1_requested = 1;
-
- BX_DEBUG(( " allow_irq12 set to %u", (unsigned)
- BX_KEY_THIS s.kbd_controller.allow_irq12));
- if ( !scan_convert )
- BX_ERROR(("keyboard: (mch) scan convert turned off"));
-
- // (mch) NT needs this
- BX_KEY_THIS s.kbd_controller.scancodes_translate = scan_convert;
- }
- break;
- case 0xd1: // write output port
- BX_DEBUG(("write output port with value %02xh",
- (unsigned) value));
- BX_SET_ENABLE_A20( (value & 0x02) != 0 );
- if (!(value & 0x01))
- BX_PANIC(("IO write: processor reset requested!"));
- break;
- case 0xd4: // Write to mouse
- // I don't think this enables the AUX clock
- //set_aux_clock_enable(1); // enable aux clock line
- kbd_ctrl_to_mouse(value);
- // ??? should I reset to previous value of aux enable?
- break;
-
- case 0xd3: // write mouse output buffer
- // Queue in mouse output buffer
- controller_enQ(value, 1);
- break;
-
- case 0xd2:
- // Queue in keyboard output buffer
- controller_enQ(value, 0);
- break;
-
- default:
- BX_PANIC(("=== unsupported write to port 60h(lastcomm=%02x): %02x",
- (unsigned) BX_KEY_THIS s.kbd_controller.last_comm, (unsigned) value));
- }
- }
- else {
- // data byte written last to 0x60
- BX_KEY_THIS s.kbd_controller.c_d = 0;
- BX_KEY_THIS s.kbd_controller.expecting_port60h = 0;
- /* pass byte to keyboard */
- /* ??? should conditionally pass to mouse device here ??? */
- if (BX_KEY_THIS s.kbd_controller.kbd_clock_enabled==0) {
- BX_ERROR(("keyboard disabled & send of byte %02x to kbd",
- (unsigned) value));
- }
- kbd_ctrl_to_kbd(value);
- }
- break;
-
- case 0x64: // control register
- // command byte written last to 0x64
- BX_KEY_THIS s.kbd_controller.c_d = 1;
- BX_KEY_THIS s.kbd_controller.last_comm = value;
- // most commands NOT expecting port60 write next
- BX_KEY_THIS s.kbd_controller.expecting_port60h = 0;
-
- switch (value) {
- case 0x20: // get keyboard command byte
- BX_DEBUG(("get keyboard command byte"));
- // controller output buffer must be empty
- if (BX_KEY_THIS s.kbd_controller.outb) {
- BX_ERROR(("kbd: OUTB set and command 0x%02x encountered", value));
- break;
- }
- command_byte =
- (BX_KEY_THIS s.kbd_controller.scancodes_translate << 6) |
- ((!BX_KEY_THIS s.kbd_controller.aux_clock_enabled) << 5) |
- ((!BX_KEY_THIS s.kbd_controller.kbd_clock_enabled) << 4) |
- (0 << 3) |
- (BX_KEY_THIS s.kbd_controller.sysf << 2) |
- (BX_KEY_THIS s.kbd_controller.allow_irq12 << 1) |
- (BX_KEY_THIS s.kbd_controller.allow_irq1 << 0);
- controller_enQ(command_byte, 0);
- break;
- case 0x60: // write command byte
- BX_DEBUG(("write command byte"));
- // following byte written to port 60h is command byte
- BX_KEY_THIS s.kbd_controller.expecting_port60h = 1;
- break;
-
- case 0xa0:
- BX_DEBUG(("keyboard BIOS name not supported"));
- break;
-
- case 0xa1:
- BX_DEBUG(("keyboard BIOS version not supported"));
- break;
-
- case 0xa7: // disable the aux device
- set_aux_clock_enable(0);
- BX_DEBUG(("aux device disabled"));
- break;
- case 0xa8: // enable the aux device
- set_aux_clock_enable(1);
- BX_DEBUG(("aux device enabled"));
- break;
- case 0xa9: // Test Mouse Port
- // controller output buffer must be empty
- if (BX_KEY_THIS s.kbd_controller.outb) {
- BX_PANIC(("kbd: OUTB set and command 0x%02x encountered", value));
- break;
- }
- controller_enQ(0x00, 0); // no errors detected
- break;
- case 0xaa: // motherboard controller self test
- BX_DEBUG(("Self Test"));
- if( kbd_initialized == 0 )
- {
- BX_KEY_THIS s.controller_Qsize = 0;
- BX_KEY_THIS s.kbd_controller.outb = 0;
- kbd_initialized++;
- }
- // controller output buffer must be empty
- if (BX_KEY_THIS s.kbd_controller.outb) {
- BX_ERROR(("kbd: OUTB set and command 0x%02x encountered", value));
- break;
- }
- // (mch) Why is this commented out??? Enabling
- BX_KEY_THIS s.kbd_controller.sysf = 1; // self test complete
- controller_enQ(0x55, 0); // controller OK
- break;
- case 0xab: // Interface Test
- // controller output buffer must be empty
- if (BX_KEY_THIS s.kbd_controller.outb) {
-BX_PANIC(("kbd: OUTB set and command 0x%02x encountered", value));
- break;
- }
- controller_enQ(0x00, 0);
- break;
- case 0xad: // disable keyboard
- set_kbd_clock_enable(0);
- BX_DEBUG(("keyboard disabled"));
- break;
- case 0xae: // enable keyboard
- set_kbd_clock_enable(1);
- BX_DEBUG(("keyboard enabled"));
- break;
- case 0xc0: // read input port
- // controller output buffer must be empty
- if (BX_KEY_THIS s.kbd_controller.outb) {
-BX_PANIC(("kbd: OUTB set and command 0x%02x encountered", value));
- break;
- }
- // keyboard power normal
- controller_enQ(0x00, 0);
- break;
- case 0xd0: // read output port: next byte read from port 60h
- BX_DEBUG(("io write to port 64h, command d0h (partial)"));
- // controller output buffer must be empty
- if (BX_KEY_THIS s.kbd_controller.outb) {
-BX_PANIC(("kbd: OUTB set and command 0x%02x encountered", value));
- break;
- }
- controller_enQ(
- (BX_KEY_THIS s.kbd_controller.auxb << 5) |
- (BX_KEY_THIS s.kbd_controller.outb << 4) |
- (BX_GET_ENABLE_A20() << 1) |
- 0x01, 0);
- break;
-
- case 0xd1: // write output port: next byte written to port 60h
- BX_DEBUG(("write output port"));
- // following byte to port 60h written to output port
- BX_KEY_THIS s.kbd_controller.expecting_port60h = 1;
- break;
-
- case 0xd3: // write mouse output buffer
- //FIXME: Why was this a panic?
- BX_DEBUG(("io write 0x64: command = 0xD3(write mouse outb)"));
- // following byte to port 60h written to output port as mouse write.
- BX_KEY_THIS s.kbd_controller.expecting_port60h = 1;
- break;
-
- case 0xd4: // write to mouse
- BX_DEBUG(("io write 0x64: command = 0xD4 (write to mouse)"));
- // following byte written to port 60h
- BX_KEY_THIS s.kbd_controller.expecting_port60h = 1;
- break;
-
- case 0xd2: // write keyboard output buffer
- BX_DEBUG(("io write 0x64: write keyboard output buffer"));
- BX_KEY_THIS s.kbd_controller.expecting_port60h = 1;
- break;
- case 0xdd: // Disable A20 Address Line
- BX_SET_ENABLE_A20(0);
- break;
- case 0xdf: // Enable A20 Address Line
- BX_SET_ENABLE_A20(1);
- break;
- case 0xc1: // Continuous Input Port Poll, Low
- case 0xc2: // Continuous Input Port Poll, High
- case 0xe0: // Read Test Inputs
- BX_PANIC(("io write 0x64: command = %02xh", (unsigned) value));
- break;
-
- case 0xfe: // System Reset, transition to real mode
- BX_INFO(("system reset"));
- bx_pc_system.ResetSignal( PCS_SET ); /* XXX is this right? */
- {
- for (int i=0; i<BX_SMP_PROCESSORS; i++)
- BX_CPU(i)->reset(BX_RESET_HARDWARE);
- }
- // Use bx_pc_system if necessary bx_cpu.reset_cpu();
- // bx_pc_system.ResetSignal( PCS_SET );
- break;
-
- default:
- if (value==0xff || (value>=0xf0 && value<=0xfd)) {
- /* useless pulse output bit commands ??? */
- BX_DEBUG(("io write to port 64h, useless command %02x",
- (unsigned) value));
- return;
- }
- BX_PANIC(("unsupported io write to keyboard port %x, value = %x",
- (unsigned) address, (unsigned) value));
- break;
- }
- break;
-
- default: BX_PANIC(("unknown address in bx_keyb_c::write()"));
- }
-}
-
-// service_paste_buf() transfers data from the paste buffer to the hardware
-// keyboard buffer. It tries to transfer as many chars as possible at a
-// time, but because different chars require different numbers of scancodes
-// we have to be conservative. Note that this process depends on the
-// keymap tables to know what chars correspond to what keys, and which
-// chars require a shift or other modifier.
-void
-bx_keyb_c::service_paste_buf ()
-{
- if (!BX_KEY_THIS pastebuf) return;
- BX_DEBUG (("service_paste_buf: ptr at %d out of %d", BX_KEY_THIS pastebuf_ptr, BX_KEY_THIS pastebuf_len));
- int fill_threshold = BX_KBD_ELEMENTS - 8;
- while ( (BX_KEY_THIS pastebuf_ptr < BX_KEY_THIS pastebuf_len) && ! BX_KEY_THIS stop_paste) {
- if (BX_KEY_THIS s.kbd_internal_buffer.num_elements >= fill_threshold)
- return;
- // there room in the buffer for a keypress and a key release.
- // send one keypress and a key release.
- Bit8u byte = BX_KEY_THIS pastebuf[BX_KEY_THIS pastebuf_ptr];
- BXKeyEntry *entry = bx_keymap.findAsciiChar (byte);
- if (!entry) {
- BX_ERROR (("paste character 0x%02x ignored", byte));
- } else {
- BX_DEBUG (("pasting character 0x%02x. baseKey is %04x", byte, entry->baseKey));
- if (entry->modKey != BX_KEYMAP_UNKNOWN)
- BX_KEY_THIS gen_scancode (entry->modKey);
- BX_KEY_THIS gen_scancode (entry->baseKey);
- BX_KEY_THIS gen_scancode (entry->baseKey | BX_KEY_RELEASED);
- if (entry->modKey != BX_KEYMAP_UNKNOWN)
- BX_KEY_THIS gen_scancode (entry->modKey | BX_KEY_RELEASED);
- }
- BX_KEY_THIS pastebuf_ptr++;
- }
- // reached end of pastebuf. free the memory it was using.
- delete [] BX_KEY_THIS pastebuf;
- BX_KEY_THIS pastebuf = NULL;
- BX_KEY_THIS stop_paste = 0;
-}
-
-// paste_bytes schedules an arbitrary number of ASCII characters to be
-// inserted into the hardware queue as it become available. Any previous
-// paste which is still in progress will be thrown out. BYTES is a pointer
-// to a region of memory containing the chars to be pasted. When the paste
-// is complete, the keyboard code will call delete [] bytes;
-void
-bx_keyb_c::paste_bytes (Bit8u *bytes, Bit32s length)
-{
- BX_DEBUG (("paste_bytes: %d bytes", length));
- if (BX_KEY_THIS pastebuf) {
- BX_ERROR (("previous paste was not completed! %d chars lost",
- BX_KEY_THIS pastebuf_len - BX_KEY_THIS pastebuf_ptr));
- delete [] BX_KEY_THIS pastebuf; // free the old paste buffer
- }
- BX_KEY_THIS pastebuf = bytes;
- BX_KEY_THIS pastebuf_ptr = 0;
- BX_KEY_THIS pastebuf_len = length;
- BX_KEY_THIS service_paste_buf ();
-}
-
- void
-bx_keyb_c::gen_scancode(Bit32u key)
-{
- unsigned char *scancode;
- Bit8u i;
-
- BX_DEBUG(( "gen_scancode(): %s %s", bx_keymap.getBXKeyName(key), (key >> 31)?"released":"pressed"));
-
- if (!BX_KEY_THIS s.kbd_controller.scancodes_translate)
- BX_DEBUG(("keyboard: gen_scancode with scancode_translate cleared"));
-
- // Ignore scancode if keyboard clock is driven low
- if (BX_KEY_THIS s.kbd_controller.kbd_clock_enabled==0)
- return;
-
- // Ignore scancode if scanning is disabled
- if (BX_KEY_THIS s.kbd_internal_buffer.scanning_enabled==0)
- return;
-
- // Switch between make and break code
- if (key & BX_KEY_RELEASED)
- scancode=(unsigned char *)scancodes[(key&0xFF)][BX_KEY_THIS s.kbd_controller.current_scancodes_set].brek;
- else
- scancode=(unsigned char *)scancodes[(key&0xFF)][BX_KEY_THIS s.kbd_controller.current_scancodes_set].make;
-
- if (BX_KEY_THIS s.kbd_controller.scancodes_translate) {
- // Translate before send
- Bit8u escaped=0x00;
-
- for (i=0; i<strlen( (const char *)scancode ); i++) {
- if (scancode[i] == 0xF0)
- escaped=0x80;
- else {
- BX_DEBUG(("gen_scancode(): writing translated %02x",translation8042[scancode[i] ] | escaped));
- kbd_enQ(translation8042[scancode[i] ] | escaped );
- escaped=0x00;
- }
- }
- }
- else {
- // Send raw data
- for (i=0; i<strlen( (const char *)scancode ); i++) {
- BX_DEBUG(("gen_scancode(): writing raw %02x",scancode[i]));
- kbd_enQ( scancode[i] );
- }
- }
-}
-
-
-
- void BX_CPP_AttrRegparmN(1)
-bx_keyb_c::set_kbd_clock_enable(Bit8u value)
-{
- bx_bool prev_kbd_clock_enabled;
-
- if (value==0) {
- BX_KEY_THIS s.kbd_controller.kbd_clock_enabled = 0;
- }
- else {
- /* is another byte waiting to be sent from the keyboard ? */
- prev_kbd_clock_enabled = BX_KEY_THIS s.kbd_controller.kbd_clock_enabled;
- BX_KEY_THIS s.kbd_controller.kbd_clock_enabled = 1;
-
- if (prev_kbd_clock_enabled==0 && BX_KEY_THIS s.kbd_controller.outb==0) {
- activate_timer();
- }
- }
-}
-
-
-
- void
-bx_keyb_c::set_aux_clock_enable(Bit8u value)
-{
- bx_bool prev_aux_clock_enabled;
-
- BX_DEBUG(("set_aux_clock_enable(%u)", (unsigned) value));
- if (value==0) {
- BX_KEY_THIS s.kbd_controller.aux_clock_enabled = 0;
- }
- else {
- /* is another byte waiting to be sent from the keyboard ? */
- prev_aux_clock_enabled = BX_KEY_THIS s.kbd_controller.aux_clock_enabled;
- BX_KEY_THIS s.kbd_controller.aux_clock_enabled = 1;
- if (prev_aux_clock_enabled==0 && BX_KEY_THIS s.kbd_controller.outb==0)
- activate_timer();
- }
-}
-
- Bit8u
-bx_keyb_c::get_kbd_enable(void)
-{
- BX_DEBUG(("get_kbd_enable(): getting kbd_clock_enabled of: %02x",
- (unsigned) BX_KEY_THIS s.kbd_controller.kbd_clock_enabled));
-
- return(BX_KEY_THIS s.kbd_controller.kbd_clock_enabled);
-}
-
- void
-bx_keyb_c::controller_enQ(Bit8u data, unsigned source)
-{
- // source is 0 for keyboard, 1 for mouse
-
- BX_DEBUG(("controller_enQ(%02x) source=%02x", (unsigned) data,source));
-
- if (BX_KEY_THIS s.kbd_controller.outb)
- BX_ERROR(("controller_enQ(): OUTB set!"));
-
- // see if we need to Q this byte from the controller
- // remember this includes mouse bytes.
- if (BX_KEY_THIS s.kbd_controller.outb) {
- if (BX_KEY_THIS s.controller_Qsize >= BX_KBD_CONTROLLER_QSIZE)
- BX_PANIC(("controller_enq(): controller_Q full!"));
- BX_KEY_THIS s.controller_Q[BX_KEY_THIS s.controller_Qsize++] = data;
- BX_KEY_THIS s.controller_Qsource = source;
- return;
- }
-
- // the Q is empty
- if (source == 0) { // keyboard
- BX_KEY_THIS s.kbd_controller.kbd_output_buffer = data;
- // BX_INFO(("kbd: %04d outb 1 auxb 0",__LINE__)); // das
- BX_KEY_THIS s.kbd_controller.outb = 1;
- BX_KEY_THIS s.kbd_controller.auxb = 0;
- BX_KEY_THIS s.kbd_controller.inpb = 0;
- if (BX_KEY_THIS s.kbd_controller.allow_irq1)
- BX_KEY_THIS s.kbd_controller.irq1_requested = 1;
- }
- else { // mouse
- BX_KEY_THIS s.kbd_controller.aux_output_buffer = data;
- // BX_INFO(("kbd: %04d outb 1 auxb 1",__LINE__)); // das
- BX_KEY_THIS s.kbd_controller.outb = 1;
- BX_KEY_THIS s.kbd_controller.auxb = 1;
- BX_KEY_THIS s.kbd_controller.inpb = 0;
- if (BX_KEY_THIS s.kbd_controller.allow_irq12)
- BX_KEY_THIS s.kbd_controller.irq12_requested = 1;
- }
-}
-
-void
-bx_keyb_c::kbd_enQ_imm(Bit8u val)
-{
- int tail;
-
- if (BX_KEY_THIS s.kbd_internal_buffer.num_elements >= BX_KBD_ELEMENTS) {
- BX_PANIC(("internal keyboard buffer full (imm)"));
- return;
- }
-
- /* enqueue scancode in multibyte internal keyboard buffer */
- tail = (BX_KEY_THIS s.kbd_internal_buffer.head + BX_KEY_THIS s.kbd_internal_buffer.num_elements) %
- BX_KBD_ELEMENTS;
-
- BX_KEY_THIS s.kbd_controller.kbd_output_buffer = val;
- // BX_INFO(("kbd: %04d outb 1",__LINE__)); // das
- BX_KEY_THIS s.kbd_controller.outb = 1;
-
- if (BX_KEY_THIS s.kbd_controller.allow_irq1)
- BX_KEY_THIS s.kbd_controller.irq1_requested = 1;
-}
-
-
- void
-bx_keyb_c::kbd_enQ(Bit8u scancode)
-{
- int tail;
-
- BX_DEBUG(("kbd_enQ(0x%02x)", (unsigned) scancode));
-
- if (BX_KEY_THIS s.kbd_internal_buffer.num_elements >= BX_KBD_ELEMENTS) {
- BX_INFO(("internal keyboard buffer full, ignoring scancode.(%02x)",
- (unsigned) scancode));
- return;
- }
-
- /* enqueue scancode in multibyte internal keyboard buffer */
- BX_DEBUG(("kbd_enQ: putting scancode 0x%02x in internal buffer",
- (unsigned) scancode));
- tail = (BX_KEY_THIS s.kbd_internal_buffer.head + BX_KEY_THIS s.kbd_internal_buffer.num_elements) %
- BX_KBD_ELEMENTS;
- BX_KEY_THIS s.kbd_internal_buffer.buffer[tail] = scancode;
- BX_KEY_THIS s.kbd_internal_buffer.num_elements++;
-
- if (!BX_KEY_THIS s.kbd_controller.outb && BX_KEY_THIS s.kbd_controller.kbd_clock_enabled) {
- activate_timer();
- BX_DEBUG(("activating timer..."));
- return;
- }
-//BX_DEBUG(( "# not activating timer...");
-//BX_DEBUG(( "# allow_irq1 = %u", (unsigned) BX_KEY_THIS s.kbd_controller.allow_irq1);
-//BX_DEBUG(( "# outb = %u", (unsigned) BX_KEY_THIS s.kbd_controller.outb);
-//BX_DEBUG(( "# clock_enab = %u", (unsigned) BX_KEY_THIS s.kbd_controller.kbd_clock_enabled);
-//BX_DEBUG(( "# out_buffer = %u", (unsigned) BX_KEY_THIS s.kbd_controller.kbd_output_buffer);
-}
-
- bx_bool BX_CPP_AttrRegparmN(3)
-bx_keyb_c::mouse_enQ_packet(Bit8u b1, Bit8u b2, Bit8u b3)
-{
- if ((BX_KEY_THIS s.mouse_internal_buffer.num_elements + 3) >= BX_MOUSE_BUFF_SIZE) {
- return(0); /* buffer doesn't have the space */
- }
-
-//BX_DEBUG(("mouse: enQ_packet(%02x, %02x, %02x)",
-// (unsigned) b1, (unsigned) b2, (unsigned) b3));
-
- mouse_enQ(b1);
- mouse_enQ(b2);
- mouse_enQ(b3);
- return(1);
-}
-
-
- void
-bx_keyb_c::mouse_enQ(Bit8u mouse_data)
-{
- int tail;
-
- BX_DEBUG(("mouse_enQ(%02x)", (unsigned) mouse_data));
-
- if (BX_KEY_THIS s.mouse_internal_buffer.num_elements >= BX_MOUSE_BUFF_SIZE) {
- BX_ERROR(("mouse: internal mouse buffer full, ignoring mouse data.(%02x)",
- (unsigned) mouse_data));
- return;
- }
-//BX_DEBUG(( "# mouse_enq() aux_clock_enabled = %u",
-// (unsigned) BX_KEY_THIS s.kbd_controller.aux_clock_enabled);
-
- /* enqueue mouse data in multibyte internal mouse buffer */
- tail = (BX_KEY_THIS s.mouse_internal_buffer.head + BX_KEY_THIS s.mouse_internal_buffer.num_elements) %
- BX_MOUSE_BUFF_SIZE;
- BX_KEY_THIS s.mouse_internal_buffer.buffer[tail] = mouse_data;
- BX_KEY_THIS s.mouse_internal_buffer.num_elements++;
-
- if (!BX_KEY_THIS s.kbd_controller.outb && BX_KEY_THIS s.kbd_controller.aux_clock_enabled) {
- activate_timer();
-//BX_DEBUG(( "# activating timer...");
- return;
- }
-//BX_DEBUG(( "# not activating timer...");
-//BX_DEBUG(( "# allow_irq12= %u", (unsigned) BX_KEY_THIS s.kbd_controller.allow_irq12);
-//BX_DEBUG(( "# outb = %u", (unsigned) BX_KEY_THIS s.kbd_controller.outb);
-//BX_DEBUG(( "# clock_enab = %u", (unsigned) BX_KEY_THIS s.kbd_controller.aux_clock_enabled);
-//BX_DEBUG(( "# out_buffer = %u", (unsigned) BX_KEY_THIS s.kbd_controller.aux_output_buffer);
-}
-
- void
-bx_keyb_c::kbd_ctrl_to_kbd(Bit8u value)
-{
-
- BX_DEBUG(("controller passed byte %02xh to keyboard", value));
-
- if (BX_KEY_THIS s.kbd_internal_buffer.expecting_typematic) {
- BX_KEY_THIS s.kbd_internal_buffer.expecting_typematic = 0;
- BX_KEY_THIS s.kbd_internal_buffer.delay = (value >> 5) & 0x03;
- switch (BX_KEY_THIS s.kbd_internal_buffer.delay) {
- case 0: BX_INFO(("setting delay to 250 mS (unused)")); break;
- case 1: BX_INFO(("setting delay to 500 mS (unused)")); break;
- case 2: BX_INFO(("setting delay to 750 mS (unused)")); break;
- case 3: BX_INFO(("setting delay to 1000 mS (unused)")); break;
- }
- BX_KEY_THIS s.kbd_internal_buffer.repeat_rate = value & 0x1f;
- double cps = 1 /((double)(8 + (value & 0x07)) * (double)exp(log((double)2) * (double)((value >> 3) & 0x03)) * 0.00417);
- BX_INFO(("setting repeat rate to %.1f cps (unused)", cps));
- kbd_enQ(0xFA); // send ACK
- return;
- }
-
- if (BX_KEY_THIS s.kbd_internal_buffer.expecting_led_write) {
- BX_KEY_THIS s.kbd_internal_buffer.expecting_led_write = 0;
- BX_KEY_THIS s.kbd_internal_buffer.led_status = value;
- BX_DEBUG(("LED status set to %02x",
- (unsigned) BX_KEY_THIS s.kbd_internal_buffer.led_status));
- kbd_enQ(0xFA); // send ACK %%%
- return;
- }
-
- if (BX_KEY_THIS s.kbd_controller.expecting_scancodes_set) {
- BX_KEY_THIS s.kbd_controller.expecting_scancodes_set = 0;
- if( value != 0 ) {
- if( value<4 ) {
- BX_KEY_THIS s.kbd_controller.current_scancodes_set = (value-1);
- BX_INFO(("Switched to scancode set %d\n",
- (unsigned) BX_KEY_THIS s.kbd_controller.current_scancodes_set + 1));
- kbd_enQ(0xFA);
- }
- else {
- BX_ERROR(("Received scancodes set out of range: %d\n", value ));
- kbd_enQ(0xFF); // send ERROR
- }
- }
- else {
- // Send current scancodes set to port 0x60
- kbd_enQ( 1 + (BX_KEY_THIS s.kbd_controller.current_scancodes_set) );
- }
- return;
- }
-
- switch (value) {
- case 0x00: // ??? ignore and let OS timeout with no response
- kbd_enQ(0xFA); // send ACK %%%
- return;
- break;
-
- case 0x05: // ???
- // (mch) trying to get this to work...
- BX_KEY_THIS s.kbd_controller.sysf = 1;
- kbd_enQ_imm(0xfe);
- return;
- break;
-
- case 0xed: // LED Write
- BX_KEY_THIS s.kbd_internal_buffer.expecting_led_write = 1;
- kbd_enQ_imm(0xFA); // send ACK %%%
- return;
- break;
-
- case 0xee: // echo
- kbd_enQ(0xEE); // return same byte (EEh) as echo diagnostic
- return;
- break;
-
- case 0xf0: // Select alternate scan code set
- BX_KEY_THIS s.kbd_controller.expecting_scancodes_set = 1;
- BX_DEBUG(("Expecting scancode set info...\n"));
- kbd_enQ(0xFA); // send ACK
- return;
- break;
-
- case 0xf2: // identify keyboard
- BX_INFO(("identify keyboard command received"));
-
- // XT sends nothing, AT sends ACK
- // MFII with translation sends ACK+ABh+41h
- // MFII without translation sends ACK+ABh+83h
- if (bx_options.Okeyboard_type->get() != BX_KBD_XT_TYPE) {
- kbd_enQ(0xFA);
- if (bx_options.Okeyboard_type->get() == BX_KBD_MF_TYPE) {
- kbd_enQ(0xAB);
-
- if(BX_KEY_THIS s.kbd_controller.scancodes_translate)
- kbd_enQ(0x41);
- else
- kbd_enQ(0x83);
- }
- }
- return;
- break;
-
- case 0xf3: // typematic info
- BX_KEY_THIS s.kbd_internal_buffer.expecting_typematic = 1;
- BX_INFO(("setting typematic info"));
- kbd_enQ(0xFA); // send ACK
- return;
- break;
-
- case 0xf4: // enable keyboard
- BX_KEY_THIS s.kbd_internal_buffer.scanning_enabled = 1;
- kbd_enQ(0xFA); // send ACK
- return;
- break;
-
- case 0xf5: // reset keyboard to power-up settings and disable scanning
- resetinternals(1);
- kbd_enQ(0xFA); // send ACK
- BX_KEY_THIS s.kbd_internal_buffer.scanning_enabled = 0;
- BX_INFO(("reset-disable command received"));
- return;
- break;
-
- case 0xf6: // reset keyboard to power-up settings and enable scanning
- resetinternals(1);
- kbd_enQ(0xFA); // send ACK
- BX_KEY_THIS s.kbd_internal_buffer.scanning_enabled = 1;
- BX_INFO(("reset-enable command received"));
- return;
- break;
-
- case 0xf7: // PS/2 Set All Keys To Typematic
- case 0xf8: // PS/2 Set All Keys to Make/Break
- case 0xf9: // PS/2 PS/2 Set All Keys to Make
- case 0xfa: // PS/2 Set All Keys to Typematic Make/Break
- case 0xfb: // PS/2 Set Key Type to Typematic
- case 0xfc: // PS/2 Set Key Type to Make/Break
- case 0xfd: // PS/2 Set Key Type to Make
- // Silently ignore and let the OS timeout, for now.
- // If anyone has code around that makes use of that, I can
- // provide documentation on their behavior (ask core@ggi-project.org)
- return;
- break;
-
- case 0xfe: // resend. aiiee.
- BX_PANIC( ("got 0xFE (resend)"));
- return;
- break;
-
- case 0xff: // reset: internal keyboard reset and afterwards the BAT
- BX_DEBUG(("reset command received"));
- resetinternals(1);
- kbd_enQ(0xFA); // send ACK
- kbd_enQ(0xAA); // BAT test passed
- return;
- break;
-
- case 0xd3:
- kbd_enQ(0xfa);
- return;
-
- default:
- /* XXX fix this properly:
- http://panda.cs.ndsu.nodak.edu/~achapwes/PICmicro/mouse/mouse.html
- http://sourceforge.net/tracker/index.php?func=detail&aid=422457&group_id=12580&atid=112580
- */
- BX_ERROR(("kbd_ctrl_to_kbd(): got value of %02x",
- (unsigned) value));
- kbd_enQ(0xFA); /* send ACK ??? */
- return;
- break;
- }
-}
-
- void
-bx_keyb_c::timer_handler(void *this_ptr)
-{
- bx_keyb_c *class_ptr = (bx_keyb_c *) this_ptr;
- unsigned retval;
-
- // retval=class_ptr->periodic( bx_options.Okeyboard_serial_delay->get());
- retval=class_ptr->periodic(1);
-
- if(retval&0x01)
- DEV_pic_raise_irq(1);
- if(retval&0x02)
- DEV_pic_raise_irq(12);
-}
-
- unsigned
-bx_keyb_c::periodic( Bit32u usec_delta )
-{
-/* static int multiple=0; */
- static unsigned count_before_paste=0;
- Bit8u retval;
-
- UNUSED( usec_delta );
-
- if (BX_KEY_THIS s.kbd_controller.kbd_clock_enabled ) {
- if(++count_before_paste>=BX_KEY_THIS pastedelay) {
- // after the paste delay, consider adding moving more chars
- // from the paste buffer to the keyboard buffer.
- BX_KEY_THIS service_paste_buf ();
- count_before_paste=0;
- }
- }
-
- retval = BX_KEY_THIS s.kbd_controller.irq1_requested | (BX_KEY_THIS s.kbd_controller.irq12_requested << 1);
- BX_KEY_THIS s.kbd_controller.irq1_requested = 0;
- BX_KEY_THIS s.kbd_controller.irq12_requested = 0;
-
- if ( BX_KEY_THIS s.kbd_controller.timer_pending == 0 ) {
- return(retval);
- }
-
- if ( usec_delta >= BX_KEY_THIS s.kbd_controller.timer_pending ) {
- BX_KEY_THIS s.kbd_controller.timer_pending = 0;
- }
- else {
- BX_KEY_THIS s.kbd_controller.timer_pending -= usec_delta;
- return(retval);
- }
-
- if (BX_KEY_THIS s.kbd_controller.outb) {
- return(retval);
- }
-
- /* nothing in outb, look for possible data xfer from keyboard or mouse */
- if (BX_KEY_THIS s.kbd_controller.kbd_clock_enabled && BX_KEY_THIS s.kbd_internal_buffer.num_elements) {
-//BX_DEBUG(( "# servicing keyboard code");
- BX_DEBUG(("service_keyboard: key in internal buffer waiting"));
- BX_KEY_THIS s.kbd_controller.kbd_output_buffer =
- BX_KEY_THIS s.kbd_internal_buffer.buffer[BX_KEY_THIS s.kbd_internal_buffer.head];
- // BX_INFO(("kbd: %04d outb 1",__LINE__)); // das
- BX_KEY_THIS s.kbd_controller.outb = 1;
- // commented out since this would override the current state of the
- // mouse buffer flag - no bug seen - just seems wrong (das)
- // BX_KEY_THIS s.kbd_controller.auxb = 0;
-//BX_DEBUG(( "# ___kbd::periodic kbd");
- BX_KEY_THIS s.kbd_internal_buffer.head = (BX_KEY_THIS s.kbd_internal_buffer.head + 1) %
- BX_KBD_ELEMENTS;
- BX_KEY_THIS s.kbd_internal_buffer.num_elements--;
- if (BX_KEY_THIS s.kbd_controller.allow_irq1)
- BX_KEY_THIS s.kbd_controller.irq1_requested = 1;
- }
- else {
- create_mouse_packet(0);
- if (BX_KEY_THIS s.kbd_controller.aux_clock_enabled && BX_KEY_THIS s.mouse_internal_buffer.num_elements) {
-//BX_DEBUG(( "# servicing mouse code");
- BX_DEBUG(("service_keyboard: key(from mouse) in internal buffer waiting"));
- BX_KEY_THIS s.kbd_controller.aux_output_buffer =
- BX_KEY_THIS s.mouse_internal_buffer.buffer[BX_KEY_THIS s.mouse_internal_buffer.head];
-
- // BX_INFO(("kbd: %04d outb 1 auxb 1",__LINE__)); //das
- BX_KEY_THIS s.kbd_controller.outb = 1;
- BX_KEY_THIS s.kbd_controller.auxb = 1;
-//BX_DEBUG(( "# ___kbd:periodic aux");
- BX_KEY_THIS s.mouse_internal_buffer.head = (BX_KEY_THIS s.mouse_internal_buffer.head + 1) %
- BX_MOUSE_BUFF_SIZE;
- BX_KEY_THIS s.mouse_internal_buffer.num_elements--;
-//BX_DEBUG(( "# allow12 = %u", (unsigned) BX_KEY_THIS s.kbd_controller.allow_irq12);
- if (BX_KEY_THIS s.kbd_controller.allow_irq12)
- BX_KEY_THIS s.kbd_controller.irq12_requested = 1;
- }
- else {
- BX_DEBUG(("service_keyboard(): no keys waiting"));
- }
- }
- return(retval);
-}
-
-
-
-
- void
-bx_keyb_c::activate_timer(void)
-{
- if (BX_KEY_THIS s.kbd_controller.timer_pending == 0) {
- // BX_KEY_THIS s.kbd_controller.timer_pending = bx_options.Okeyboard_serial_delay->get ();
- BX_KEY_THIS s.kbd_controller.timer_pending = 1;
- }
-}
-
-
- void
-bx_keyb_c::kbd_ctrl_to_mouse(Bit8u value)
-{
-BX_DEBUG(("MOUSE: kbd_ctrl_to_mouse(%02xh)", (unsigned) value));
-BX_DEBUG((" enable = %u", (unsigned) BX_KEY_THIS s.mouse.enable));
-BX_DEBUG((" allow_irq12 = %u",
- (unsigned) BX_KEY_THIS s.kbd_controller.allow_irq12));
-BX_DEBUG((" aux_clock_enabled = %u",
- (unsigned) BX_KEY_THIS s.kbd_controller.aux_clock_enabled));
-//BX_DEBUG(( "MOUSE: kbd_ctrl_to_mouse(%02xh)", (unsigned) value));
-
- // an ACK (0xFA) is always the first response to any valid input
- // received from the system other than Set-Wrap-Mode & Resend-Command
-
-
- if (BX_KEY_THIS s.kbd_controller.expecting_mouse_parameter) {
- BX_KEY_THIS s.kbd_controller.expecting_mouse_parameter = 0;
- switch (BX_KEY_THIS s.kbd_controller.last_mouse_command) {
- case 0xf3: // Set Mouse Sample Rate
- BX_KEY_THIS s.mouse.sample_rate = value;
- BX_DEBUG(("[mouse] Sampling rate set: %d Hz", value));
- controller_enQ(0xFA, 1); // ack
- break;
-
- case 0xe8: // Set Mouse Resolution
- switch (value) {
- case 0:
- BX_KEY_THIS s.mouse.resolution_cpmm = 1;
- break;
- case 1:
- BX_KEY_THIS s.mouse.resolution_cpmm = 2;
- break;
- case 2:
- BX_KEY_THIS s.mouse.resolution_cpmm = 4;
- break;
- case 3:
- BX_KEY_THIS s.mouse.resolution_cpmm = 8;
- break;
- default:
- BX_PANIC(("[mouse] Unknown resolution %d", value));
- break;
- }
- BX_DEBUG(("[mouse] Resolution set to %d counts per mm",
- BX_KEY_THIS s.mouse.resolution_cpmm));
-
- controller_enQ(0xFA, 1); // ack
- break;
-
- default:
- BX_PANIC(("MOUSE: unknown last command (%02xh)", (unsigned) BX_KEY_THIS s.kbd_controller.last_mouse_command));
- }
- } else {
- BX_KEY_THIS s.kbd_controller.expecting_mouse_parameter = 0;
- BX_KEY_THIS s.kbd_controller.last_mouse_command = value;
-
- // test for wrap mode first
- if (BX_KEY_THIS s.mouse.mode == MOUSE_MODE_WRAP) {
- // if not a reset command or reset wrap mode
- // then just echo the byte.
- if ((value != 0xff) && (value != 0xec)) {
- if (bx_dbg.mouse)
- BX_INFO(("[mouse] wrap mode: Ignoring command %0X02.",value));
- controller_enQ(value,1);
- // bail out
- return;
- }
- }
- switch ( value ) {
- case 0xe6: // Set Mouse Scaling to 1:1
- controller_enQ(0xFA, 1); // ACK
- BX_KEY_THIS s.mouse.scaling = 2;
- BX_DEBUG(("[mouse] Scaling set to 1:1"));
- break;
-
- case 0xe7: // Set Mouse Scaling to 2:1
- controller_enQ(0xFA, 1); // ACK
- BX_KEY_THIS s.mouse.scaling = 2;
- BX_DEBUG(("[mouse] Scaling set to 2:1"));
- break;
-
- case 0xe8: // Set Mouse Resolution
- controller_enQ(0xFA, 1); // ACK
- BX_KEY_THIS s.kbd_controller.expecting_mouse_parameter = 1;
- break;
-
- case 0xea: // Set Stream Mode
- if (bx_dbg.mouse)
- BX_INFO(("[mouse] Mouse stream mode on."));
- BX_KEY_THIS s.mouse.mode = MOUSE_MODE_STREAM;
- controller_enQ(0xFA, 1); // ACK
- break;
-
- case 0xec: // Reset Wrap Mode
- // unless we are in wrap mode ignore the command
- if ( BX_KEY_THIS s.mouse.mode == MOUSE_MODE_WRAP) {
- if (bx_dbg.mouse)
- BX_INFO(("[mouse] Mouse wrap mode off."));
- // restore previous mode except disable stream mode reporting.
- // ### TODO disabling reporting in stream mode
- BX_KEY_THIS s.mouse.mode = BX_KEY_THIS s.mouse.saved_mode;
- controller_enQ(0xFA, 1); // ACK
- }
- break;
- case 0xee: // Set Wrap Mode
- // ### TODO flush output queue.
- // ### TODO disable interrupts if in stream mode.
- if (bx_dbg.mouse)
- BX_INFO(("[mouse] Mouse wrap mode on."));
- BX_KEY_THIS s.mouse.saved_mode = BX_KEY_THIS s.mouse.mode;
- BX_KEY_THIS s.mouse.mode = MOUSE_MODE_WRAP;
- controller_enQ(0xFA, 1); // ACK
- break;
-
- case 0xf0: // Set Remote Mode (polling mode, i.e. not stream mode.)
- if (bx_dbg.mouse)
- BX_INFO(("[mouse] Mouse remote mode on."));
- // ### TODO should we flush/discard/ignore any already queued packets?
- BX_KEY_THIS s.mouse.mode = MOUSE_MODE_REMOTE;
- controller_enQ(0xFA, 1); // ACK
- break;
-
-
- case 0xf2: // Read Device Type
- controller_enQ(0xFA, 1); // ACK
- controller_enQ(0x00, 1); // Device ID
- BX_DEBUG(("[mouse] Read mouse ID"));
- break;
-
- case 0xf3: // Set Mouse Sample Rate (sample rate written to port 60h)
- controller_enQ(0xFA, 1); // ACK
- BX_KEY_THIS s.kbd_controller.expecting_mouse_parameter = 1;
- break;
-
- case 0xf4: // Enable (in stream mode)
- BX_KEY_THIS s.mouse.enable = 1;
- controller_enQ(0xFA, 1); // ACK
- BX_DEBUG(("[mouse] Mouse enabled (stream mode)"));
- break;
-
- case 0xf5: // Disable (in stream mode)
- BX_KEY_THIS s.mouse.enable = 0;
- controller_enQ(0xFA, 1); // ACK
- BX_DEBUG(("[mouse] Mouse disabled (stream mode)"));
- break;
-
- case 0xf6: // Set Defaults
- BX_KEY_THIS s.mouse.sample_rate = 100; /* reports per second (default) */
- BX_KEY_THIS s.mouse.resolution_cpmm = 4; /* 4 counts per millimeter (default) */
- BX_KEY_THIS s.mouse.scaling = 1; /* 1:1 (default) */
- BX_KEY_THIS s.mouse.enable = 0;
- BX_KEY_THIS s.mouse.mode = MOUSE_MODE_STREAM;
- controller_enQ(0xFA, 1); // ACK
- BX_DEBUG(("[mouse] Set Defaults"));
- break;
-
- case 0xff: // Reset
- BX_KEY_THIS s.mouse.sample_rate = 100; /* reports per second (default) */
- BX_KEY_THIS s.mouse.resolution_cpmm = 4; /* 4 counts per millimeter (default) */
- BX_KEY_THIS s.mouse.scaling = 1; /* 1:1 (default) */
- BX_KEY_THIS s.mouse.mode = MOUSE_MODE_RESET;
- BX_KEY_THIS s.mouse.enable = 0;
- /* (mch) NT expects an ack here */
- controller_enQ(0xFA, 1); // ACK
- controller_enQ(0xAA, 1); // completion code
- controller_enQ(0x00, 1); // ID code (normal mouse, wheelmouse has id 0x3)
- BX_DEBUG(("[mouse] Mouse reset"));
- break;
-
- case 0xe9: // Get mouse information
- // should we ack here? (mch): Yes
- controller_enQ(0xFA, 1); // ACK
- controller_enQ(BX_KEY_THIS s.mouse.get_status_byte(), 1); // status
- controller_enQ(BX_KEY_THIS s.mouse.get_resolution_byte(), 1); // resolution
- controller_enQ(BX_KEY_THIS s.mouse.sample_rate, 1); // sample rate
- BX_DEBUG(("[mouse] Get mouse information"));
- break;
-
- case 0xeb: // Read Data (send a packet when in Remote Mode)
- controller_enQ(0xFA, 1); // ACK
- // perhaps we should be adding some movement here.
- mouse_enQ_packet( ((BX_KEY_THIS s.mouse.button_status & 0x0f) | 0x08),
- 0x00, 0x00 ); // bit3 of first byte always set
- //assumed we really aren't in polling mode, a rather odd assumption.
- BX_ERROR(("[mouse] Warning: Read Data command partially supported."));
- break;
-
- default:
- //FEh Resend
- BX_PANIC(("MOUSE: kbd_ctrl_to_mouse(%02xh)", (unsigned) value));
- }
- }
-}
-
-void
-bx_keyb_c::create_mouse_packet(bool force_enq) {
- Bit8u b1, b2, b3;
-
- // BX_DEBUG("Calling create_mouse_packet: force_enq=%d\n",force_enq);
-
- if(BX_KEY_THIS s.mouse_internal_buffer.num_elements && !force_enq)
- return;
-
- // BX_DEBUG("Got to first milestone: force_enq=%d\n",force_enq);
-
- Bit16s delta_x = BX_KEY_THIS s.mouse.delayed_dx;
- Bit16s delta_y = BX_KEY_THIS s.mouse.delayed_dy;
- Bit8u button_state=BX_KEY_THIS s.mouse.button_status | 0x08;
-
- if(!force_enq && !delta_x && !delta_y) {
- return;
- }
-
- // BX_DEBUG("Got to second milestone: delta_x=%d, delta_y=%d\n",delta_x,delta_y);
-
- if(delta_x>254) delta_x=254;
- if(delta_x<-254) delta_x=-254;
- if(delta_y>254) delta_y=254;
- if(delta_y<-254) delta_y=-254;
-
- b1 = (button_state & 0x0f) | 0x08; // bit3 always set
-
- if ( (delta_x>=0) && (delta_x<=255) ) {
- b2 = (Bit8u) delta_x;
- BX_KEY_THIS s.mouse.delayed_dx-=delta_x;
- }
- else if ( delta_x > 255 ) {
- b2 = (Bit8u) 0xff;
- BX_KEY_THIS s.mouse.delayed_dx-=255;
- }
- else if ( delta_x >= -256 ) {
- b2 = (Bit8u) delta_x;
- b1 |= 0x10;
- BX_KEY_THIS s.mouse.delayed_dx-=delta_x;
- }
- else {
- b2 = (Bit8u) 0x00;
- b1 |= 0x10;
- BX_KEY_THIS s.mouse.delayed_dx+=256;
- }
-
- if ( (delta_y>=0) && (delta_y<=255) ) {
- b3 = (Bit8u) delta_y;
- BX_KEY_THIS s.mouse.delayed_dy-=delta_y;
- }
- else if ( delta_y > 255 ) {
- b3 = (Bit8u) 0xff;
- BX_KEY_THIS s.mouse.delayed_dy-=255;
- }
- else if ( delta_y >= -256 ) {
- b3 = (Bit8u) delta_y;
- b1 |= 0x20;
- BX_KEY_THIS s.mouse.delayed_dy-=delta_y;
- }
- else {
- b3 = (Bit8u) 0x00;
- b1 |= 0x20;
- BX_KEY_THIS s.mouse.delayed_dy+=256;
- }
- mouse_enQ_packet(b1, b2, b3);
-}
-
-
-void
-bx_keyb_c::mouse_enabled_changed(bool enabled) {
- if(s.mouse.delayed_dx || BX_KEY_THIS s.mouse.delayed_dy) {
- create_mouse_packet(1);
- }
- s.mouse.delayed_dx=0;
- s.mouse.delayed_dy=0;
- BX_DEBUG(("Keyboard mouse disable called."));
-}
-
- void
-bx_keyb_c::mouse_motion(int delta_x, int delta_y, unsigned button_state)
-{
- bool force_enq=0;
-
- // If mouse events are disabled on the GUI headerbar, don't
- // generate any mouse data
- if (bx_options.Omouse_enabled->get () == 0)
- return;
-
-
- // don't generate interrupts if we are in remote mode.
- if ( BX_KEY_THIS s.mouse.mode == MOUSE_MODE_REMOTE)
- // is there any point in doing any work if we don't act on the result
- // so go home.
- return;
-
-
- // Note: enable only applies in STREAM MODE.
- if ( BX_KEY_THIS s.mouse.enable==0 )
- return;
-
- // scale down the motion
- if ( (delta_x < -1) || (delta_x > 1) )
- delta_x /= 2;
- if ( (delta_y < -1) || (delta_y > 1) )
- delta_y /= 2;
-
-#ifdef VERBOSE_KBD_DEBUG
- if (delta_x != 0 || delta_y != 0)
- BX_DEBUG(("[mouse] Dx=%d Dy=%d", delta_x, delta_y));
-#endif /* ifdef VERBOSE_KBD_DEBUG */
-
- if( (delta_x==0) && (delta_y==0) && (BX_KEY_THIS s.mouse.button_status == (button_state & 0x3) ) ) {
- BX_DEBUG(("Ignoring useless mouse_motion call:\n"));
- BX_DEBUG(("This should be fixed in the gui code.\n"));
- return;
- }
-
- if(BX_KEY_THIS s.mouse.button_status != (button_state & 0x3)) {
- force_enq=1;
- }
-
- BX_KEY_THIS s.mouse.button_status = button_state & 0x3;
-
- if(delta_x>255) delta_x=255;
- if(delta_y>255) delta_y=255;
- if(delta_x<-256) delta_x=-256;
- if(delta_y<-256) delta_y=-256;
-
- BX_KEY_THIS s.mouse.delayed_dx+=delta_x;
- BX_KEY_THIS s.mouse.delayed_dy+=delta_y;
-
- if((BX_KEY_THIS s.mouse.delayed_dx>255)||
- (BX_KEY_THIS s.mouse.delayed_dx<-256)||
- (BX_KEY_THIS s.mouse.delayed_dy>255)||
- (BX_KEY_THIS s.mouse.delayed_dy<-256)) {
- force_enq=1;
- }
-
- create_mouse_packet(force_enq);
-}
-
-
- int
-bx_keyb_c::SaveState( class state_file *fd )
-{
- fd->write_check ("keyboard start");
- fd->write (&BX_KEY_THIS s, sizeof (BX_KEY_THIS s));
- fd->write_check ("keyboard end");
- return(0);
-}
-
-
- int
-bx_keyb_c::LoadState( class state_file *fd )
-{
- fd->read_check ("keyboard start");
- fd->read (&BX_KEY_THIS s, sizeof (BX_KEY_THIS s));
- fd->read_check ("keyboard end");
- return(0);
-}
-
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: keyboard.h,v 1.22 2003/07/13 19:51:21 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2001 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-#ifndef _PCKEY_H
-#define _PCKEY_H
-
-
-#define BX_KBD_ELEMENTS 16
-#define BX_MOUSE_BUFF_SIZE 48
-
-// these keywords should only be used in keyboard.cc
-#if BX_USE_KEY_SMF
-# define BX_KEY_SMF static
-# define BX_KEY_THIS theKeyboard->
-#else
-# define BX_KEY_SMF
-# define BX_KEY_THIS
-#endif
-
-#define MOUSE_MODE_RESET 10
-#define MOUSE_MODE_STREAM 11
-#define MOUSE_MODE_REMOTE 12
-#define MOUSE_MODE_WRAP 13
-
-class bx_keyb_c : public bx_keyb_stub_c {
-public:
- bx_keyb_c(void);
- ~bx_keyb_c(void);
- // implement bx_devmodel_c interface
- virtual void init(void);
- virtual void reset(unsigned type);
- // override stubs from bx_keyb_stub_c
- virtual void gen_scancode(Bit32u key);
- virtual void paste_bytes(Bit8u *data, Bit32s length);
- virtual void mouse_motion(int delta_x, int delta_y, unsigned button_state);
-
- // update the paste delay based on bx_options.Okeyboard_paste_delay
- virtual void paste_delay_changed ();
- virtual void mouse_enabled_changed(bool enabled);
-
-private:
- BX_KEY_SMF Bit8u get_kbd_enable(void);
- BX_KEY_SMF void service_paste_buf ();
- BX_KEY_SMF void create_mouse_packet(bool force_enq);
- BX_KEY_SMF void mouse_button(unsigned mouse_state);
- BX_KEY_SMF int SaveState( class state_file *fd );
- BX_KEY_SMF int LoadState( class state_file *fd );
- BX_KEY_SMF unsigned periodic( Bit32u usec_delta );
-
-
- static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len);
- static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len);
-#if !BX_USE_KEY_SMF
- void write(Bit32u address, Bit32u value, unsigned io_len);
- Bit32u read(Bit32u address, unsigned io_len);
-#endif
-
- struct {
- struct {
- /* status bits matching the status port*/
- bx_bool pare; // Bit7, 1= parity error from keyboard/mouse - ignored.
- bx_bool tim; // Bit6, 1= timeout from keyboard - ignored.
- bx_bool auxb; // Bit5, 1= mouse data waiting for CPU to read.
- bx_bool keyl; // Bit4, 1= keyswitch in lock position - ignored.
- bx_bool c_d; /* Bit3, 1=command to port 64h, 0=data to port 60h */
- bx_bool sysf; // Bit2,
- bx_bool inpb; // Bit1,
- bx_bool outb; // Bit0, 1= keyboard data or mouse data ready for CPU
- // check aux to see which. Or just keyboard
- // data before AT style machines
-
- /* internal to our version of the keyboard controller */
- bx_bool kbd_clock_enabled;
- bx_bool aux_clock_enabled;
- bx_bool allow_irq1;
- bx_bool allow_irq12;
- Bit8u kbd_output_buffer;
- Bit8u aux_output_buffer;
- Bit8u last_comm;
- Bit8u expecting_port60h;
- Bit8u expecting_mouse_parameter;
- Bit8u last_mouse_command;
- Bit32u timer_pending;
- bx_bool irq1_requested;
- bx_bool irq12_requested;
- bx_bool scancodes_translate;
- bx_bool expecting_scancodes_set;
- Bit8u current_scancodes_set;
- } kbd_controller;
-
- struct mouseStruct {
- Bit8u sample_rate;
- Bit8u resolution_cpmm; // resolution in counts per mm
- Bit8u scaling;
- Bit8u mode;
- Bit8u saved_mode; // the mode prior to entering wrap mode
- bx_bool enable;
-
- Bit8u get_status_byte ()
- {
- // top bit is 0 , bit 6 is 1 if remote mode.
- Bit8u ret = (Bit8u) ((mode == MOUSE_MODE_REMOTE) ? 0x40 : 0);
- ret |= (enable << 5);
- ret |= (scaling == 1) ? 0 : (1 << 4);
- ret |= ((button_status & 0x1) << 2);
- ret |= ((button_status & 0x2) << 0);
- return ret;
- }
-
- Bit8u get_resolution_byte ()
- {
- Bit8u ret = 0;
-
- switch (resolution_cpmm) {
- case 1:
- ret = 0;
- break;
-
- case 2:
- ret = 1;
- break;
-
- case 4:
- ret = 2;
- break;
-
- case 8:
- ret = 3;
- break;
-
- default:
- genlog->panic("mouse: invalid resolution_cpmm");
- };
- return ret;
- }
-
- Bit8u button_status;
- Bit16s delayed_dx;
- Bit16s delayed_dy;
- } mouse;
-
- struct {
- int num_elements;
- Bit8u buffer[BX_KBD_ELEMENTS];
- int head;
- bx_bool expecting_typematic;
- bx_bool expecting_led_write;
- Bit8u delay;
- Bit8u repeat_rate;
- Bit8u led_status;
- bx_bool scanning_enabled;
- } kbd_internal_buffer;
-
- struct {
- int num_elements;
- Bit8u buffer[BX_MOUSE_BUFF_SIZE];
- int head;
- } mouse_internal_buffer;
-#define BX_KBD_CONTROLLER_QSIZE 5
- Bit8u controller_Q[BX_KBD_CONTROLLER_QSIZE];
- unsigned controller_Qsize;
- unsigned controller_Qsource; // 0=keyboard, 1=mouse
- } s; // State information for saving/loading
-
- // The paste buffer does NOT exist in the hardware. It is a bochs
- // construction that allows the user to "paste" arbitrary length sequences of
- // keystrokes into the emulated machine. Since the hardware buffer is only
- // 16 bytes, a very small amount of data can be added to the hardware buffer
- // at a time. The paste buffer keeps track of the bytes that have not yet
- // been pasted.
- //
- // Lifetime of a paste buffer: The paste data comes from the system
- // clipboard, which must be accessed using platform independent code in the
- // gui. Because every gui has its own way of managing the clipboard memory
- // (in X windows, you're supposed to call Xfree for example), in the platform
- // specific code we make a copy of the clipboard buffer with
- // "new Bit8u[length]". Then the pointer is passed into
- // bx_keyb_c::paste_bytes, along with the length. The gui code never touches
- // the pastebuf again, and does not free it. The keyboard code is
- // responsible for deallocating the paste buffer using delete [] buf. The
- // paste buffer is binary data, and it is probably NOT null terminated.
- //
- // Summary: A paste buffer is allocated (new) in the platform-specific gui
- // code, passed to the keyboard model, and is freed (delete[]) when it is no
- // longer needed.
- Bit8u *pastebuf; // ptr to bytes to be pasted, or NULL if none in progress
- Bit32u pastebuf_len; // length of pastebuf
- Bit32u pastebuf_ptr; // ptr to next byte to be added to hw buffer
- Bit32u pastedelay; // count before paste
- bx_bool stop_paste; // stop the current paste operation on hardware reset
-
- BX_KEY_SMF void resetinternals(bx_bool powerup);
- BX_KEY_SMF void set_kbd_clock_enable(Bit8u value) BX_CPP_AttrRegparmN(1);
- BX_KEY_SMF void set_aux_clock_enable(Bit8u value);
- BX_KEY_SMF void kbd_ctrl_to_kbd(Bit8u value);
- BX_KEY_SMF void kbd_ctrl_to_mouse(Bit8u value);
- BX_KEY_SMF void kbd_enQ(Bit8u scancode);
- BX_KEY_SMF void kbd_enQ_imm(Bit8u val);
- BX_KEY_SMF void activate_timer(void);
- BX_KEY_SMF void controller_enQ(Bit8u data, unsigned source);
- BX_KEY_SMF bx_bool mouse_enQ_packet(Bit8u b1, Bit8u b2, Bit8u b3) BX_CPP_AttrRegparmN(3);
- BX_KEY_SMF void mouse_enQ(Bit8u mouse_data);
-
- static void timer_handler(void *);
- void timer(void);
- int timer_handle;
- };
-
-
-#endif // #ifndef _PCKEY_H
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: load32bitOShack.cc,v 1.14 2003/08/08 00:05:53 cbothamy Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2001 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-
-
-#include "bochs.h"
-#define LOG_THIS genlog->
-
-
-
-static void bx_load_linux_hack(void);
-static void bx_load_null_kernel_hack(void);
-static Bit32u bx_load_kernel_image(char *path, Bit32u paddr);
-
- void
-bx_load32bitOSimagehack(void)
-{
- // Replay IO from log to initialize IO devices to
- // a reasonable state needed for the OS. This is done
- // in lieu of running the 16-bit BIOS to init things,
- // since we want to test straight 32bit stuff for
- // freemware.
-
-#ifndef BX_USE_VMX
- FILE *fp;
-
- fp = fopen(bx_options.load32bitOSImage.Oiolog->getptr (), "r");
-
- if (fp == NULL) {
- BX_PANIC(("could not open IO init file."));
- }
-
- while (1) {
- unsigned len, op, port, val;
- int ret;
- ret = fscanf(fp, "%u %u %x %x\n",
- &len, &op, &port, &val);
- if (ret != 4) {
- BX_PANIC(("could not open IO init file."));
- }
- if (op == 0) {
- // read
- (void) bx_devices.inp(port, len);
- }
- else if (op == 1) {
- // write
- bx_devices.outp(port, val, len);
- }
- else {
- BX_PANIC(("bad IO op in init filen"));
- }
- if (feof(fp)) break;
- }
-#endif
-
- // Invoke proper hack depending on which OS image we're loading
- switch (bx_options.load32bitOSImage.OwhichOS->get ()) {
- case Load32bitOSLinux:
- bx_load_linux_hack();
- break;
- case Load32bitOSNullKernel:
- bx_load_null_kernel_hack();
- break;
- default:
- BX_PANIC(("load32bitOSImage: OS not recognized"));
- }
-}
-
-struct gdt_entry
-{
- Bit32u low;
- Bit32u high;
-};
-struct linux_setup_params
-{
- /* 0x000 */ Bit8u orig_x;
- /* 0x001 */ Bit8u orig_y;
- /* 0x002 */ Bit16u memory_size_std;
- /* 0x004 */ Bit16u orig_video_page;
- /* 0x006 */ Bit8u orig_video_mode;
- /* 0x007 */ Bit8u orig_video_cols;
- /* 0x008 */ Bit16u unused1;
- /* 0x00a */ Bit16u orig_video_ega_bx;
- /* 0x00c */ Bit16u unused2;
- /* 0x00e */ Bit8u orig_video_lines;
- /* 0x00f */ Bit8u orig_video_isVGA;
- /* 0x010 */ Bit16u orig_video_points;
- /* 0x012 */ Bit8u pad1[0x40 - 0x12];
- /* 0x040 */ Bit8u apm_info[0x80 - 0x40];
- /* 0x080 */ Bit8u hd0_info[16];
- /* 0x090 */ Bit8u hd1_info[16];
- /* 0x0a0 */ Bit8u pad2[0x1e0 - 0xa0];
- /* 0x1e0 */ Bit32u memory_size_ext;
- /* 0x1e4 */ Bit8u pad3[0x1f1 - 0x1e4];
- /* 0x1f1 */ Bit8u setup_sects;
- /* 0x1f2 */ Bit16u mount_root_rdonly;
- /* 0x1f4 */ Bit16u sys_size;
- /* 0x1f6 */ Bit16u swap_dev;
- /* 0x1f8 */ Bit16u ramdisk_flags;
- /* 0x1fa */ Bit16u vga_mode;
- /* 0x1fc */ Bit16u orig_root_dev;
- /* 0x1fe */ Bit16u bootsect_magic;
- /* 0x200 */ Bit8u pad4[0x210 - 0x200];
- /* 0x210 */ Bit32u loader_type;
- /* 0x214 */ Bit32u kernel_start;
- /* 0x218 */ Bit32u initrd_start;
- /* 0x21c */ Bit32u initrd_size;
- /* 0x220 */ Bit8u pad5[0x400 - 0x220];
- /* 0x400 */ struct gdt_entry gdt[128];
- /* 0x800 */ Bit8u commandline[2048];
-};
-
- static void
-bx_load_linux_setup_params( Bit32u initrd_start, Bit32u initrd_size )
-{
- BX_MEM_C *mem = BX_MEM(0);
- struct linux_setup_params *params =
- (struct linux_setup_params *) &mem->vector[0x00090000];
-
- memset( params, '\0', sizeof(*params) );
-
- /* Video settings (standard VGA) */
- params->orig_x = 0;
- params->orig_y = 0;
- params->orig_video_page = 0;
- params->orig_video_mode = 3;
- params->orig_video_cols = 80;
- params->orig_video_lines = 25;
- params->orig_video_points = 16;
- params->orig_video_isVGA = 1;
- params->orig_video_ega_bx = 3;
-
- /* Memory size (total mem - 1MB, in KB) */
- params->memory_size_ext = (mem->megabytes - 1) * 1024;
-
- /* Boot parameters */
- params->loader_type = 1;
- params->bootsect_magic = 0xaa55;
- params->mount_root_rdonly = 0;
- params->orig_root_dev = 0x0100;
- params->initrd_start = initrd_start;
- params->initrd_size = initrd_size;
-
- /* Initial GDT */
- params->gdt[2].high = 0x00cf9a00;
- params->gdt[2].low = 0x0000ffff;
- params->gdt[3].high = 0x00cf9200;
- params->gdt[3].low = 0x0000ffff;
-}
-
- void
-bx_load_linux_hack(void)
-{
-#ifndef BX_USE_VMX
- Bit32u initrd_start = 0, initrd_size = 0;
-
- // The RESET function will have been called first.
- // Set CPU and memory features which are assumed at this point.
-
- // Load Linux kernel image
- bx_load_kernel_image( bx_options.load32bitOSImage.Opath->getptr (), 0x100000 );
-
- // Load initial ramdisk image if requested
- if ( bx_options.load32bitOSImage.Oinitrd->getptr () )
- {
- initrd_start = 0x00800000; /* FIXME: load at top of memory */
- initrd_size = bx_load_kernel_image( bx_options.load32bitOSImage.Oinitrd->getptr (), initrd_start );
- }
-
- // Setup Linux startup parameters buffer
- bx_load_linux_setup_params( initrd_start, initrd_size );
-#endif
-
- // Enable A20 line
- BX_SET_ENABLE_A20( 1 );
-
- // Setup PICs the way Linux likes it
- BX_OUTP( 0x20, 0x11, 1 );
- BX_OUTP( 0xA0, 0x11, 1 );
- BX_OUTP( 0x21, 0x20, 1 );
- BX_OUTP( 0xA1, 0x28, 1 );
- BX_OUTP( 0x21, 0x04, 1 );
- BX_OUTP( 0xA1, 0x02, 1 );
- BX_OUTP( 0x21, 0x01, 1 );
- BX_OUTP( 0xA1, 0x01, 1 );
- BX_OUTP( 0x21, 0xFF, 1 );
- BX_OUTP( 0xA1, 0xFB, 1 );
-
-#ifndef BX_USE_VMX
- // Disable interrupts and NMIs
- BX_CPU(0)->clear_IF ();
-#endif
-
- BX_OUTP( 0x70, 0x80, 1 );
-
-#ifndef BX_USE_VMX
- // Enter protected mode
- // Fixed by george (kyriazis at nvidia.com)
- // BX_CPU(0)->cr0.pe = 1;
- // BX_CPU(0)->cr0.val32 |= 0x01;
-
- BX_CPU(0)->SetCR0(BX_CPU(0)->cr0.val32 | 0x01);
-
- // load esi with real_mode
- BX_CPU(0)->gen_reg[BX_32BIT_REG_ESI].dword.erx = 0x90000;
-
- // Set up initial GDT
- BX_CPU(0)->gdtr.limit = 0x400;
- BX_CPU(0)->gdtr.base = 0x00090400;
-
- // Jump to protected mode entry point
- BX_CPU(0)->jump_protected( NULL, 0x10, 0x00100000 );
-#endif
-}
-
- void
-bx_load_null_kernel_hack(void)
-{
-#ifndef BX_USE_VMX
- // The RESET function will have been called first.
- // Set CPU and memory features which are assumed at this point.
-
- bx_load_kernel_image(bx_options.load32bitOSImage.Opath->getptr (), 0x100000);
-
- // EIP deltas
- BX_CPU(0)->prev_eip =
- BX_CPU(0)->dword.eip = 0x00100000;
-
- // CS deltas
- BX_CPU(0)->sregs[BX_SEG_REG_CS].cache.u.segment.base = 0x00000000;
- BX_CPU(0)->sregs[BX_SEG_REG_CS].cache.u.segment.limit = 0xFFFFF;
- BX_CPU(0)->sregs[BX_SEG_REG_CS].cache.u.segment.limit_scaled = 0xFFFFFFFF;
- BX_CPU(0)->sregs[BX_SEG_REG_CS].cache.u.segment.g = 1; // page gran
- BX_CPU(0)->sregs[BX_SEG_REG_CS].cache.u.segment.d_b = 1; // 32bit
-
- // DS deltas
- BX_CPU(0)->sregs[BX_SEG_REG_DS].cache.u.segment.base = 0x00000000;
- BX_CPU(0)->sregs[BX_SEG_REG_DS].cache.u.segment.limit = 0xFFFFF;
- BX_CPU(0)->sregs[BX_SEG_REG_DS].cache.u.segment.limit_scaled = 0xFFFFFFFF;
- BX_CPU(0)->sregs[BX_SEG_REG_DS].cache.u.segment.g = 1; // page gran
- BX_CPU(0)->sregs[BX_SEG_REG_DS].cache.u.segment.d_b = 1; // 32bit
-
- // CR0 deltas
- BX_CPU(0)->cr0.pe = 1; // protected mode
-#endif // BX_USE_VMX
-}
-
- Bit32u
-bx_load_kernel_image(char *path, Bit32u paddr)
-{
- struct stat stat_buf;
- int fd, ret;
- unsigned long size, offset;
- Bit32u page_size;
-
- // read in ROM BIOS image file
- fd = open(path, O_RDONLY
-#ifdef O_BINARY
- | O_BINARY
-#endif
- );
- if (fd < 0) {
- BX_INFO(( "load_kernel_image: couldn't open image file '%s'.", path ));
- BX_EXIT(1);
- }
- ret = fstat(fd, &stat_buf);
- if (ret) {
- BX_INFO(( "load_kernel_image: couldn't stat image file '%s'.", path ));
- BX_EXIT(1);
- }
-
- size = stat_buf.st_size;
- page_size = ((Bit32u)size + 0xfff) & ~0xfff;
-
- BX_MEM_C *mem = BX_MEM(0);
- if ( (paddr + size) > mem->len ) {
- BX_INFO(( "load_kernel_image: address range > physical memsize!" ));
- BX_EXIT(1);
- }
-
- offset = 0;
- while (size > 0) {
- ret = read(fd, (bx_ptr_t) &mem->vector[paddr + offset], size);
- if (ret <= 0) {
- BX_INFO(( "load_kernel_image: read failed on image" ));
- BX_EXIT(1);
- }
- size -= ret;
- offset += ret;
- }
- close(fd);
- BX_INFO(( "#(%u) load_kernel_image: '%s', size=%u read into memory at %08x",
- BX_SIM_ID, path,
- (unsigned) stat_buf.st_size,
- (unsigned) paddr ));
-
- return page_size;
-}
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: logio.cc,v 1.42 2003/08/24 10:30:07 cbothamy Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2001 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-
-#include "bochs.h"
-#include <assert.h>
-#include "state_file.h"
-
-#if BX_WITH_CARBON
-#include <Carbon/Carbon.h>
-#endif
-
-// Just for the iofunctions
-
-
-int Allocio=0;
-
-void
-iofunctions::flush(void) {
- if(logfd && magic == MAGIC_LOGNUM) {
- fflush(logfd);
- }
-}
-
-void
-iofunctions::init(void) {
- // iofunctions methods must not be called before this magic
- // number is set.
- magic=MAGIC_LOGNUM;
-
- // sets the default logprefix
- strcpy(logprefix,"%t%e%d");
- n_logfn = 0;
- init_log(stderr);
- log = new logfunc_t(this);
- log->put("IO");
- log->settype(IOLOG);
- log->ldebug ("Init(log file: '%s').",logfn);
-}
-
-void
-iofunctions::add_logfn (logfunc_t *fn)
-{
- assert (n_logfn < MAX_LOGFNS);
- logfn_list[n_logfn++] = fn;
-}
-
-void
-iofunctions::set_log_action (int loglevel, int action)
-{
- for (int i=0; i<n_logfn; i++)
- logfn_list[i]->setonoff(loglevel, action);
-}
-
-void
-iofunctions::init_log(const char *fn)
-{
- assert (magic==MAGIC_LOGNUM);
- // use newfd/newfn so that we can log the message to the OLD log
- // file descriptor.
- FILE *newfd = stderr;
- char *newfn = "/dev/stderr";
- if( strcmp( fn, "-" ) != 0 ) {
- newfd = fopen(fn, "w");
- if(newfd != NULL) {
- newfn = strdup(fn);
- log->ldebug ("Opened log file '%s'.", fn );
- } else {
- // in constructor, genlog might not exist yet, so do it the safe way.
- log->error("Couldn't open log file: %s, using stderr instead", fn);
- newfd = stderr;
- }
- }
- logfd = newfd;
- logfn = newfn;
-}
-
-void
-iofunctions::init_log(FILE *fs)
-{
- assert (magic==MAGIC_LOGNUM);
- logfd = fs;
-
- if(fs == stderr) {
- logfn = "/dev/stderr";
- } else if(fs == stdout) {
- logfn = "/dev/stdout";
- } else {
- logfn = "(unknown)";
- }
-
-}
-
-void
-iofunctions::init_log(int fd)
-{
- assert (magic==MAGIC_LOGNUM);
- FILE *tmpfd;
- if( (tmpfd = fdopen(fd,"w")) == NULL ) {
- log->panic("Couldn't open fd %d as a stream for writing", fd);
- return;
- }
-
- init_log(tmpfd);
- return;
-};
-
-// all other functions may use genlog safely.
-#define LOG_THIS genlog->
-
-// This converts the option string to a printf style string with the following args:
-// 1. timer, 2. event, 3. cpu0 eip, 4. device
-void
-iofunctions::set_log_prefix(const char* prefix) {
-
- strcpy(logprefix,prefix);
-}
-
-// iofunctions::out( class, level, prefix, fmt, ap)
-// DO NOT nest out() from ::info() and the like.
-// fmt and ap retained for direct printinf from iofunctions only!
-
-void
-iofunctions::out(int f, int l, const char *prefix, const char *fmt, va_list ap)
-{
- char c=' ', *s;
- assert (magic==MAGIC_LOGNUM);
- assert (this != NULL);
- assert (logfd != NULL);
-
- //if( showtick )
- // fprintf(logfd, "%011lld", bx_pc_system.time_ticks());
-
- switch(l) {
- case LOGLEV_INFO: c='i'; break;
- case LOGLEV_PANIC: c='p'; break;
- case LOGLEV_PASS: c='s'; break;
- case LOGLEV_ERROR: c='e'; break;
- case LOGLEV_DEBUG: c='d'; break;
- default: break;
- }
- //fprintf(logfd, "-%c",c);
-
- //if(prefix != NULL)
- // fprintf(logfd, "%s ", prefix);
-
- s=logprefix;
- while(*s) {
- switch(*s) {
- case '%':
- if(*(s+1))s++;
- else break;
- switch(*s) {
- case 'd':
- fprintf(logfd, "%s", prefix==NULL?"":prefix);
- break;
- case 't':
- fprintf(logfd, "%011lld", bx_pc_system.time_ticks());
- break;
-#ifndef BX_USE_VMX
- case 'i':
- fprintf(logfd, "%08x", BX_CPU(0)==NULL?0:BX_CPU(0)->dword.eip);
- break;
-#endif
- case 'e':
- fprintf(logfd, "%c", c);
- break;
- case '%':
- fprintf(logfd,"%%");
- break;
- default:
- fprintf(logfd,"%%%c",*s);
- }
- break;
- default :
- fprintf(logfd,"%c",*s);
- }
- s++;
- }
-
- fprintf(logfd," ");
-
- if(l==LOGLEV_PANIC)
- fprintf(logfd, ">>PANIC<< ");
- if(l==LOGLEV_PASS)
- fprintf(logfd, ">>PASS<< ");
-
- vfprintf(logfd, fmt, ap);
- fprintf(logfd, "\n");
- fflush(logfd);
-
- return;
-}
-
-iofunctions::iofunctions(FILE *fs)
-{
- init();
- init_log(fs);
-}
-
-iofunctions::iofunctions(const char *fn)
-{
- init();
- init_log(fn);
-}
-
-iofunctions::iofunctions(int fd)
-{
- init();
- init_log(fd);
-}
-
-iofunctions::iofunctions(void)
-{
- this->init();
-}
-
-iofunctions::~iofunctions(void)
-{
- // flush before erasing magic number, or flush does nothing.
- this->flush();
- this->magic=0;
-}
-
-#define LOG_THIS genlog->
-
-int logfunctions::default_onoff[N_LOGLEV] = {
- ACT_IGNORE, // ignore debug
- ACT_REPORT, // report info
- ACT_REPORT, // report error
-#if BX_WITH_WX
- ACT_ASK, // on panic, ask user what to do
-#else
- ACT_FATAL, // on panic, quit
-#endif
- ACT_FATAL
-};
-
-logfunctions::logfunctions(void)
-{
- prefix = NULL;
- put(" ");
- settype(GENLOG);
- if (io == NULL && Allocio == 0) {
- Allocio = 1;
- io = new iofunc_t(stderr);
- }
- setio(io);
- // BUG: unfortunately this can be called before the bochsrc is read,
- // which means that the bochsrc has no effect on the actions.
- for (int i=0; i<N_LOGLEV; i++)
- onoff[i] = get_default_action(i);
-}
-
-logfunctions::logfunctions(iofunc_t *iofunc)
-{
- prefix = NULL;
- put(" ");
- settype(GENLOG);
- setio(iofunc);
- // BUG: unfortunately this can be called before the bochsrc is read,
- // which means that the bochsrc has no effect on the actions.
- for (int i=0; i<N_LOGLEV; i++)
- onoff[i] = get_default_action(i);
-}
-
-logfunctions::~logfunctions(void)
-{
- if ( this->prefix )
- {
- free(this->prefix);
- this->prefix = NULL;
- }
-}
-
-void
-logfunctions::setio(iofunc_t *i)
-{
- // add pointer to iofunction object to use
- this->logio = i;
- // give iofunction a pointer to me
- i->add_logfn (this);
-}
-
-void
-logfunctions::put(char *p)
-{
- char *tmpbuf;
- tmpbuf=strdup("[ ]");// if we ever have more than 32 chars,
- // we need to rethink this
-
- if ( tmpbuf == NULL)
- {
- return ; /* allocation not successful */
- }
- if ( this->prefix != NULL )
- {
- free(this->prefix); /* free previously allocated memory */
- this->prefix = NULL;
- }
- int len=strlen(p);
- for(int i=1;i<len+1;i++) {
- tmpbuf[i]=p[i-1];
- }
-
- switch(len) {
- case 1: tmpbuf[2]=' ';
- case 2: tmpbuf[3]=' ';
- case 3: tmpbuf[4]=' ';
- case 4: tmpbuf[5]=' ';
- default: tmpbuf[6]=']'; tmpbuf[7]='\0'; break;
- }
-
- this->prefix=tmpbuf;
-}
-
-void
-logfunctions::settype(int t)
-{
- type=t;
-}
-
-void
-logfunctions::info(const char *fmt, ...)
-{
- va_list ap;
-
- assert (this != NULL);
- assert (this->logio != NULL);
-
- if(!onoff[LOGLEV_INFO]) return;
-
- va_start(ap, fmt);
- this->logio->out(this->type,LOGLEV_INFO,this->prefix, fmt, ap);
- if (onoff[LOGLEV_INFO] == ACT_ASK)
- ask (LOGLEV_INFO, this->prefix, fmt, ap);
- if (onoff[LOGLEV_INFO] == ACT_FATAL)
- fatal (this->prefix, fmt, ap, 1);
- va_end(ap);
-
-}
-
-void
-logfunctions::error(const char *fmt, ...)
-{
- va_list ap;
-
- assert (this != NULL);
- assert (this->logio != NULL);
-
- if(!onoff[LOGLEV_ERROR]) return;
-
- va_start(ap, fmt);
- this->logio->out(this->type,LOGLEV_ERROR,this->prefix, fmt, ap);
- if (onoff[LOGLEV_ERROR] == ACT_ASK)
- ask (LOGLEV_ERROR, this->prefix, fmt, ap);
- if (onoff[LOGLEV_ERROR] == ACT_FATAL)
- fatal (this->prefix, fmt, ap, 1);
- va_end(ap);
-}
-
-void
-logfunctions::panic(const char *fmt, ...)
-{
- va_list ap;
-
- assert (this != NULL);
- assert (this->logio != NULL);
-
- // Special case for panics since they are so important. Always print
- // the panic to the log, no matter what the log action says.
- //if(!onoff[LOGLEV_PANIC]) return;
-
- va_start(ap, fmt);
- this->logio->out(this->type,LOGLEV_PANIC,this->prefix, fmt, ap);
-
- // This fixes a funny bug on linuxppc where va_list is no pointer but a struct
- va_end(ap);
- va_start(ap, fmt);
-
- if (onoff[LOGLEV_PANIC] == ACT_ASK)
- ask (LOGLEV_PANIC, this->prefix, fmt, ap);
- if (onoff[LOGLEV_PANIC] == ACT_FATAL)
- fatal (this->prefix, fmt, ap, 1);
- va_end(ap);
-}
-
-void
-logfunctions::pass(const char *fmt, ...)
-{
- va_list ap;
-
- assert (this != NULL);
- assert (this->logio != NULL);
-
- // Special case for panics since they are so important. Always print
- // the panic to the log, no matter what the log action says.
- //if(!onoff[LOGLEV_PASS]) return;
-
- va_start(ap, fmt);
- this->logio->out(this->type,LOGLEV_PASS,this->prefix, fmt, ap);
-
- // This fixes a funny bug on linuxppc where va_list is no pointer but a struct
- va_end(ap);
- va_start(ap, fmt);
-
- if (onoff[LOGLEV_PASS] == ACT_ASK)
- ask (LOGLEV_PASS, this->prefix, fmt, ap);
- if (onoff[LOGLEV_PASS] == ACT_FATAL)
- fatal (this->prefix, fmt, ap, 101);
- va_end(ap);
-}
-
-void
-logfunctions::ldebug(const char *fmt, ...)
-{
- va_list ap;
-
- assert (this != NULL);
- assert (this->logio != NULL);
-
- if(!onoff[LOGLEV_DEBUG]) return;
-
- va_start(ap, fmt);
- this->logio->out(this->type,LOGLEV_DEBUG,this->prefix, fmt, ap);
- if (onoff[LOGLEV_DEBUG] == ACT_ASK)
- ask (LOGLEV_DEBUG, this->prefix, fmt, ap);
- if (onoff[LOGLEV_DEBUG] == ACT_FATAL)
- fatal (this->prefix, fmt, ap, 1);
- va_end(ap);
-}
-
-void
-logfunctions::ask (int level, const char *prefix, const char *fmt, va_list ap)
-{
- // Guard against reentry on ask() function. The danger is that some
- // function that's called within ask() could trigger another
- // BX_PANIC that could call ask() again, leading to infinite
- // recursion and infinite asks.
- static char in_ask_already = 0;
- char buf1[1024];
- if (in_ask_already) {
- fprintf (stderr, "logfunctions::ask() should not reenter!!\n");
- return;
- }
- in_ask_already = 1;
- vsprintf (buf1, fmt, ap);
- // FIXME: facility set to 0 because it's unknown.
-
- // update vga screen. This is useful because sometimes useful messages
- // are printed on the screen just before a panic. It's also potentially
- // dangerous if this function calls ask again... That's why I added
- // the reentry check above.
- if (SIM->get_init_done()) DEV_vga_refresh();
-
-#if !BX_EXTERNAL_DEBUGGER
- // ensure the text screen is showing
- SIM->set_display_mode (DISP_MODE_CONFIG);
- int val = SIM->log_msg (prefix, level, buf1);
- switch (val)
- {
- case BX_LOG_ASK_CHOICE_CONTINUE:
- break;
- case BX_LOG_ASK_CHOICE_CONTINUE_ALWAYS:
- // user said continue, and don't "ask" for this facility again.
- setonoff (level, ACT_REPORT);
- break;
- case BX_LOG_ASK_CHOICE_DIE:
- bx_user_quit = 1;
- in_ask_already = 0; // because fatal will longjmp out
- fatal (prefix, fmt, ap, 1);
- // should never get here
- BX_PANIC (("in ask(), fatal() should never return!"));
- break;
- case BX_LOG_ASK_CHOICE_DUMP_CORE:
- fprintf (stderr, "User chose to dump core...\n");
-#if BX_HAVE_ABORT
- abort ();
-#else
- // do something highly illegal that should kill the process.
- // Hey, this is fun!
- {
- char *crashptr = (char *)0; char c = *crashptr;
- }
- fprintf (stderr, "Sorry, I couldn't find your abort() function. Exiting.");
- exit (0);
-#endif
-#if BX_DEBUGGER
- case BX_LOG_ASK_CHOICE_ENTER_DEBUG:
- // user chose debugger. To "drop into the debugger" we just set the
- // interrupt_requested bit and continue execution. Before the next
- // instruction, it should notice the user interrupt and return to
- // the debugger.
- bx_guard.interrupt_requested = 1;
- break;
-#endif
- default:
- // this happens if panics happen before the callback is initialized
- // in gui/control.cc.
- fprintf (stderr, "WARNING: log_msg returned unexpected value %d\n", val);
- }
-#else
- // external debugger ask code goes here
-#endif
- // return to simulation mode
- SIM->set_display_mode (DISP_MODE_SIM);
- in_ask_already = 0;
-}
-
-#if BX_WITH_CARBON
-/* Panic button to display fatal errors.
- Completely self contained, can't rely on carbon.cc being available */
-static void carbonFatalDialog(const char *error, const char *exposition)
-{
- DialogRef alertDialog;
- CFStringRef cfError;
- CFStringRef cfExposition;
- DialogItemIndex index;
- AlertStdCFStringAlertParamRec alertParam = {0};
-
- // Init libraries
- InitCursor();
- // Assemble dialog
- cfError = CFStringCreateWithCString(NULL, error, kCFStringEncodingASCII);
- if(exposition != NULL)
- {
- cfExposition = CFStringCreateWithCString(NULL, exposition, kCFStringEncodingASCII);
- }
- else { cfExposition = NULL; }
- alertParam.version = kStdCFStringAlertVersionOne;
- alertParam.defaultText = CFSTR("Quit");
- alertParam.position = kWindowDefaultPosition;
- alertParam.defaultButton = kAlertStdAlertOKButton;
- // Display Dialog
- CreateStandardAlert(
- kAlertStopAlert,
- cfError,
- cfExposition, /* can be NULL */
- &alertParam, /* can be NULL */
- &alertDialog);
- RunStandardAlert( alertDialog, NULL, &index);
- // Cleanup
- CFRelease( cfError );
- if( cfExposition != NULL ) { CFRelease( cfExposition ); }
-}
-#endif
-
-void
-logfunctions::fatal (const char *prefix, const char *fmt, va_list ap, int exit_status)
-{
- bx_atexit();
-#if BX_WITH_CARBON
- if(!isatty(STDIN_FILENO) && !SIM->get_init_done())
- {
- char buf1[1024];
- char buf2[1024];
- vsprintf (buf1, fmt, ap);
- sprintf (buf2, "Bochs startup error\n%s", buf1);
- carbonFatalDialog(buf2,
- "For more information, try running Bochs within Terminal by clicking on \"bochs.scpt\".");
- }
-#endif
-#if !BX_WITH_WX
- static char *divider = "========================================================================";
- fprintf (stderr, "%s\n", divider);
- fprintf (stderr, "Bochs is exiting with the following message:\n");
- fprintf (stderr, "%s ", prefix);
- vfprintf (stderr, fmt, ap);
- fprintf (stderr, "\n%s\n", divider);
-#endif
-#if 0 && defined(WIN32)
-#error disabled because it is not working yet!
- // wait for a keypress before quitting. Depending on how bochs is
- // installed, the console window can disappear before the user has
- // a chance to read the final message.
- fprintf (stderr, "\n\nPress Enter to exit...\n");
- char buf[8];
- fgets (buf, 8, stdin);
-#endif
-#if !BX_DEBUGGER
- BX_EXIT(exit_status);
-#else
- static bx_bool dbg_exit_called = 0;
- if (dbg_exit_called == 0) {
- dbg_exit_called = 1;
- bx_dbg_exit(exit_status);
- }
-#endif
- // not safe to use BX_* log functions in here.
- fprintf (stderr, "fatal() should never return, but it just did\n");
-}
-
-iofunc_t *io = NULL;
-logfunc_t *genlog = NULL;
-
-void bx_center_print (FILE *file, char *line, int maxwidth)
-{
- int imax;
- int len = strlen(line);
- if (len > maxwidth)
- BX_PANIC (("bx_center_print: line is too long: '%s'", line));
- imax = (maxwidth - len) >> 1;
- for (int i=0; i<imax; i++) fputc (' ', file);
- fputs (line, file);
-}
-
-
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: main.cc,v 1.256.2.3 2004/02/08 14:39:50 cbothamy Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-// Copyright (C) 2004 Arun Sharma <arun.sharma@intel.com>
-// Copyright (C) 2004 Intel Corp
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-#include "bochs.h"
-#include <assert.h>
-#include "state_file.h"
-
-#ifdef HAVE_LOCALE_H
-#include <locale.h>
-#endif
-
-extern "C" {
-#include <signal.h>
-}
-
-#if BX_GUI_SIGHANDLER
-bx_bool bx_gui_sighandler = 0;
-#endif
-
-// single processor simulation, so there's one of everything
-BOCHSAPI BX_CPU_C bx_cpu;
-BOCHSAPI BX_MEM_C bx_mem;
-
-int xc_handle;
-int bochsrc_include_count = 0;
-
-// some prototypes from iodev/
-// I want to stay away from including iodev/iodev.h here
-Bit32u bx_unmapped_io_read_handler(Bit32u address, unsigned io_len);
-void bx_unmapped_io_write_handler(Bit32u address, Bit32u value,
- unsigned io_len);
-void bx_close_harddrive(void);
-
-
-void bx_init_bx_dbg (void);
-static char *divider = "========================================================================";
-static logfunctions thePluginLog;
-logfunctions *pluginlog = &thePluginLog;
-
-bx_startup_flags_t bx_startup_flags;
-bx_bool bx_user_quit;
-
-/* typedefs */
-
-#define LOG_THIS genlog->
-
-#if ( BX_PROVIDE_DEVICE_MODELS==1 )
-bx_pc_system_c bx_pc_system;
-class state_file state_stuff("state_file.out", "options");
-#endif
-
-bx_debug_t bx_dbg;
-
-bx_options_t bx_options; // initialized in bx_init_options()
-char *bochsrc_filename = NULL;
-
-static Bit32s parse_line_unformatted(char *context, char *line);
-static Bit32s parse_line_formatted(char *context, int num_params, char *params[]);
-static int parse_bochsrc(char *rcfile);
-
-static Bit64s
-bx_param_handler (bx_param_c *param, int set, Bit64s val)
-{
- bx_id id = param->get_id ();
- switch (id) {
- case BXP_VGA_UPDATE_INTERVAL:
- // if after init, notify the vga device to change its timer.
- if (set && SIM->get_init_done ())
- DEV_vga_set_update_interval (val);
- break;
- case BXP_MOUSE_ENABLED:
- // if after init, notify the GUI
- if (set && SIM->get_init_done ()) {
- bx_gui->mouse_enabled_changed (val!=0);
- DEV_mouse_enabled_changed (val!=0);
- }
- break;
- case BXP_NE2K_PRESENT:
- if (set) {
- int enable = (val != 0);
- SIM->get_param (BXP_NE2K_IOADDR)->set_enabled (enable);
- SIM->get_param (BXP_NE2K_IRQ)->set_enabled (enable);
- SIM->get_param (BXP_NE2K_MACADDR)->set_enabled (enable);
- SIM->get_param (BXP_NE2K_ETHMOD)->set_enabled (enable);
- SIM->get_param (BXP_NE2K_ETHDEV)->set_enabled (enable);
- SIM->get_param (BXP_NE2K_SCRIPT)->set_enabled (enable);
- }
- break;
- case BXP_LOAD32BITOS_WHICH:
- if (set) {
- int enable = (val != Load32bitOSNone);
- SIM->get_param (BXP_LOAD32BITOS_PATH)->set_enabled (enable);
- SIM->get_param (BXP_LOAD32BITOS_IOLOG)->set_enabled (enable);
- SIM->get_param (BXP_LOAD32BITOS_INITRD)->set_enabled (enable);
- }
- break;
- case BXP_ATA0_MASTER_STATUS:
- case BXP_ATA0_SLAVE_STATUS:
- case BXP_ATA1_MASTER_STATUS:
- case BXP_ATA1_SLAVE_STATUS:
- case BXP_ATA2_MASTER_STATUS:
- case BXP_ATA2_SLAVE_STATUS:
- case BXP_ATA3_MASTER_STATUS:
- case BXP_ATA3_SLAVE_STATUS:
- if ((set) && (SIM->get_init_done ())) {
- Bit8u device = id - BXP_ATA0_MASTER_STATUS;
- Bit32u handle = DEV_hd_get_device_handle (device/2, device%2);
- DEV_hd_set_cd_media_status(handle, val == BX_INSERTED);
- bx_gui->update_drive_status_buttons ();
- }
- break;
- case BXP_FLOPPYA_TYPE:
- if ((set) && (!SIM->get_init_done ())) {
- bx_options.floppya.Odevtype->set (val);
- }
- break;
- case BXP_FLOPPYA_STATUS:
- if ((set) && (SIM->get_init_done ())) {
- DEV_floppy_set_media_status(0, val == BX_INSERTED);
- bx_gui->update_drive_status_buttons ();
- }
- break;
- case BXP_FLOPPYB_TYPE:
- if ((set) && (!SIM->get_init_done ())) {
- bx_options.floppyb.Odevtype->set (val);
- }
- break;
- case BXP_FLOPPYB_STATUS:
- if ((set) && (SIM->get_init_done ())) {
- DEV_floppy_set_media_status(1, val == BX_INSERTED);
- bx_gui->update_drive_status_buttons ();
- }
- break;
- case BXP_KBD_PASTE_DELAY:
- if ((set) && (SIM->get_init_done ())) {
- DEV_kbd_paste_delay_changed ();
- }
- break;
-
- case BXP_ATA0_MASTER_MODE:
- case BXP_ATA0_SLAVE_MODE:
- case BXP_ATA1_MASTER_MODE:
- case BXP_ATA1_SLAVE_MODE:
- case BXP_ATA2_MASTER_MODE:
- case BXP_ATA2_SLAVE_MODE:
- case BXP_ATA3_MASTER_MODE:
- case BXP_ATA3_SLAVE_MODE:
- if (set) {
- int device = id - BXP_ATA0_MASTER_MODE;
- switch (val) {
- case BX_ATA_MODE_UNDOABLE:
- case BX_ATA_MODE_VOLATILE:
- //case BX_ATA_MODE_Z_UNDOABLE:
- //case BX_ATA_MODE_Z_VOLATILE:
- SIM->get_param ((bx_id)(BXP_ATA0_MASTER_JOURNAL + device))->set_enabled (1);
- break;
- default:
- SIM->get_param ((bx_id)(BXP_ATA0_MASTER_JOURNAL + device))->set_enabled (0);
- }
- }
- break;
-
- case BXP_ATA0_MASTER_TYPE:
- case BXP_ATA0_SLAVE_TYPE:
- case BXP_ATA1_MASTER_TYPE:
- case BXP_ATA1_SLAVE_TYPE:
- case BXP_ATA2_MASTER_TYPE:
- case BXP_ATA2_SLAVE_TYPE:
- case BXP_ATA3_MASTER_TYPE:
- case BXP_ATA3_SLAVE_TYPE:
- if (set) {
- int device = id - BXP_ATA0_MASTER_TYPE;
- switch (val) {
- case BX_ATA_DEVICE_DISK:
- SIM->get_param_num ((bx_id)(BXP_ATA0_MASTER_PRESENT + device))->set (1);
- SIM->get_param ((bx_id)(BXP_ATA0_MASTER_MODE + device))->set_enabled (1);
- SIM->get_param ((bx_id)(BXP_ATA0_MASTER_PATH + device))->set_enabled (1);
- //SIM->get_param ((bx_id)(BXP_ATA0_MASTER_JOURNAL + device))->set_enabled (1);
- SIM->get_param ((bx_id)(BXP_ATA0_MASTER_CYLINDERS + device))->set_enabled (1);
- SIM->get_param ((bx_id)(BXP_ATA0_MASTER_HEADS + device))->set_enabled (1);
- SIM->get_param ((bx_id)(BXP_ATA0_MASTER_SPT + device))->set_enabled (1);
- SIM->get_param ((bx_id)(BXP_ATA0_MASTER_STATUS + device))->set_enabled (0);
- SIM->get_param ((bx_id)(BXP_ATA0_MASTER_MODEL + device))->set_enabled (1);
- SIM->get_param ((bx_id)(BXP_ATA0_MASTER_BIOSDETECT + device))->set_enabled (1);
- SIM->get_param ((bx_id)(BXP_ATA0_MASTER_TRANSLATION + device))->set_enabled (1);
- SIM->get_param ((bx_id)(BXP_ATA0_MASTER_PATH + device))->set_runtime_param (0);
- SIM->get_param ((bx_id)(BXP_ATA0_MASTER_STATUS + device))->set_runtime_param (0);
- break;
- case BX_ATA_DEVICE_CDROM:
- SIM->get_param_num ((bx_id)(BXP_ATA0_MASTER_PRESENT + device))->set (1);
- SIM->get_param ((bx_id)(BXP_ATA0_MASTER_MODE + device))->set_enabled (0);
- SIM->get_param ((bx_id)(BXP_ATA0_MASTER_PATH + device))->set_enabled (1);
- SIM->get_param ((bx_id)(BXP_ATA0_MASTER_JOURNAL + device))->set_enabled (0);
- SIM->get_param ((bx_id)(BXP_ATA0_MASTER_CYLINDERS + device))->set_enabled (0);
- SIM->get_param ((bx_id)(BXP_ATA0_MASTER_HEADS + device))->set_enabled (0);
- SIM->get_param ((bx_id)(BXP_ATA0_MASTER_SPT + device))->set_enabled (0);
- SIM->get_param ((bx_id)(BXP_ATA0_MASTER_STATUS + device))->set_enabled (1);
- SIM->get_param ((bx_id)(BXP_ATA0_MASTER_MODEL + device))->set_enabled (1);
- SIM->get_param ((bx_id)(BXP_ATA0_MASTER_BIOSDETECT + device))->set_enabled (1);
- SIM->get_param ((bx_id)(BXP_ATA0_MASTER_TRANSLATION + device))->set_enabled (0);
- SIM->get_param ((bx_id)(BXP_ATA0_MASTER_PATH + device))->set_runtime_param (1);
- SIM->get_param ((bx_id)(BXP_ATA0_MASTER_STATUS + device))->set_runtime_param (1);
- break;
- }
- }
- break;
- default:
- BX_PANIC (("bx_param_handler called with unknown id %d", id));
- return -1;
- }
- return val;
-}
-
-char *bx_param_string_handler (bx_param_string_c *param, int set, char *val, int maxlen)
-{
- bx_id id = param->get_id ();
-
- int empty = 0;
- if ((strlen(val) < 1) || !strcmp ("none", val)) {
- empty = 1;
- val = "none";
- }
- switch (id) {
- case BXP_FLOPPYA_PATH:
- if (set==1) {
- if (SIM->get_init_done ()) {
- if (empty) {
- DEV_floppy_set_media_status(0, 0);
- bx_gui->update_drive_status_buttons ();
- } else {
- if (!SIM->get_param_num(BXP_FLOPPYA_TYPE)->get_enabled()) {
- BX_ERROR(("Cannot add a floppy drive at runtime"));
- bx_options.floppya.Opath->set ("none");
- }
- }
- if ((DEV_floppy_present()) &&
- (SIM->get_param_num(BXP_FLOPPYA_STATUS)->get () == BX_INSERTED)) {
- // tell the device model that we removed, then inserted the disk
- DEV_floppy_set_media_status(0, 0);
- DEV_floppy_set_media_status(0, 1);
- }
- } else {
- SIM->get_param_num(BXP_FLOPPYA_DEVTYPE)->set_enabled (!empty);
- SIM->get_param_num(BXP_FLOPPYA_TYPE)->set_enabled (!empty);
- SIM->get_param_num(BXP_FLOPPYA_STATUS)->set_enabled (!empty);
- }
- }
- break;
- case BXP_FLOPPYB_PATH:
- if (set==1) {
- if (SIM->get_init_done ()) {
- if (empty) {
- DEV_floppy_set_media_status(1, 0);
- bx_gui->update_drive_status_buttons ();
- } else {
- if (!SIM->get_param_num(BXP_FLOPPYB_TYPE)->get_enabled ()) {
- BX_ERROR(("Cannot add a floppy drive at runtime"));
- bx_options.floppyb.Opath->set ("none");
- }
- }
- if ((DEV_floppy_present()) &&
- (SIM->get_param_num(BXP_FLOPPYB_STATUS)->get () == BX_INSERTED)) {
- // tell the device model that we removed, then inserted the disk
- DEV_floppy_set_media_status(1, 0);
- DEV_floppy_set_media_status(1, 1);
- }
- } else {
- SIM->get_param_num(BXP_FLOPPYB_DEVTYPE)->set_enabled (!empty);
- SIM->get_param_num(BXP_FLOPPYB_TYPE)->set_enabled (!empty);
- SIM->get_param_num(BXP_FLOPPYB_STATUS)->set_enabled (!empty);
- }
- }
- break;
-
- case BXP_ATA0_MASTER_PATH:
- case BXP_ATA0_SLAVE_PATH:
- case BXP_ATA1_MASTER_PATH:
- case BXP_ATA1_SLAVE_PATH:
- case BXP_ATA2_MASTER_PATH:
- case BXP_ATA2_SLAVE_PATH:
- case BXP_ATA3_MASTER_PATH:
- case BXP_ATA3_SLAVE_PATH:
- if (set==1) {
- if (SIM->get_init_done ()) {
-
- Bit8u device = id - BXP_ATA0_MASTER_PATH;
- Bit32u handle = DEV_hd_get_device_handle(device/2, device%2);
-
- if (empty) {
- DEV_hd_set_cd_media_status(handle, 0);
- bx_gui->update_drive_status_buttons ();
- } else {
- if (!SIM->get_param_num((bx_id)(BXP_ATA0_MASTER_PRESENT + device))->get ()) {
- BX_ERROR(("Cannot add a cdrom drive at runtime"));
- bx_options.atadevice[device/2][device%2].Opresent->set (0);
- }
- if (SIM->get_param_num((bx_id)(BXP_ATA0_MASTER_TYPE + device))->get () != BX_ATA_DEVICE_CDROM) {
- BX_ERROR(("Device is not a cdrom drive"));
- bx_options.atadevice[device/2][device%2].Opresent->set (0);
- }
- }
- if (DEV_hd_present() &&
- (SIM->get_param_num((bx_id)(BXP_ATA0_MASTER_STATUS + device))->get () == BX_INSERTED) &&
- (SIM->get_param_num((bx_id)(BXP_ATA0_MASTER_TYPE + device))->get () == BX_ATA_DEVICE_CDROM)) {
- // tell the device model that we removed, then inserted the cd
- DEV_hd_set_cd_media_status(handle, 0);
- DEV_hd_set_cd_media_status(handle, 1);
- }
- }
- }
- break;
-
- case BXP_SCREENMODE:
- if (set==1) {
- BX_INFO (("Screen mode changed to %s", val));
- }
- break;
- default:
- BX_PANIC (("bx_string_handler called with unexpected parameter %d", param->get_id()));
- }
- return val;
-}
-
-static int
-bx_param_enable_handler (bx_param_c *param, int val)
-{
- bx_id id = param->get_id ();
- switch (id) {
- case BXP_ATA0_MASTER_STATUS:
- case BXP_ATA0_SLAVE_STATUS:
- case BXP_ATA1_MASTER_STATUS:
- case BXP_ATA1_SLAVE_STATUS:
- case BXP_ATA2_MASTER_STATUS:
- case BXP_ATA2_SLAVE_STATUS:
- case BXP_ATA3_MASTER_STATUS:
- case BXP_ATA3_SLAVE_STATUS:
- if (val != 0) {
- Bit8u device = id - BXP_ATA0_MASTER_STATUS;
-
- switch (SIM->get_param_enum ((bx_id)(BXP_ATA0_MASTER_TYPE + device))->get()) {
- case BX_ATA_DEVICE_CDROM:
- return (1);
- break;
- }
- }
- return (0);
- break;
-
- case BXP_ATA0_MASTER_JOURNAL:
- case BXP_ATA0_SLAVE_JOURNAL:
- case BXP_ATA1_MASTER_JOURNAL:
- case BXP_ATA1_SLAVE_JOURNAL:
- case BXP_ATA2_MASTER_JOURNAL:
- case BXP_ATA2_SLAVE_JOURNAL:
- case BXP_ATA3_MASTER_JOURNAL:
- case BXP_ATA3_SLAVE_JOURNAL:
- if (val != 0) {
- Bit8u device = id - BXP_ATA0_MASTER_JOURNAL;
-
- switch (SIM->get_param_enum ((bx_id)(BXP_ATA0_MASTER_TYPE + device))->get()) {
- case BX_ATA_DEVICE_DISK:
- switch (SIM->get_param_enum ((bx_id)(BXP_ATA0_MASTER_MODE + device))->get()) {
- case BX_ATA_MODE_UNDOABLE:
- case BX_ATA_MODE_VOLATILE:
- //case BX_ATA_MODE_Z_UNDOABLE:
- //case BX_ATA_MODE_Z_VOLATILE:
- return (1);
- break;
- }
- }
- }
- return (0);
- break;
-
- default:
- BX_PANIC (("bx_param_handler called with unknown id %d", id));
- }
- return val;
-}
-
-
-
-void bx_init_options ()
-{
- int i;
- bx_list_c *menu;
- bx_list_c *deplist;
- char name[1024], descr[1024], label[1024];
-
- memset (&bx_options, 0, sizeof(bx_options));
-
- // quick start option, set by command line arg
- new bx_param_enum_c (BXP_BOCHS_START,
- "Bochs start types",
- "Bochs start types",
- bochs_start_names,
- BX_RUN_START,
- BX_QUICK_START);
-
- // floppya
- bx_options.floppya.Opath = new bx_param_filename_c (BXP_FLOPPYA_PATH,
- "floppya:path",
- "Pathname of first floppy image file or device. If you're booting from floppy, this should be a bootable floppy.",
- "", BX_PATHNAME_LEN);
- bx_options.floppya.Opath->set_ask_format ("Enter new filename, or 'none' for no disk: [%s] ");
- bx_options.floppya.Opath->set_label ("First floppy image/device");
- bx_options.floppya.Odevtype = new bx_param_enum_c (BXP_FLOPPYA_DEVTYPE,
- "floppya:devtype",
- "Type of floppy drive",
- floppy_type_names,
- BX_FLOPPY_NONE,
- BX_FLOPPY_NONE);
- bx_options.floppya.Otype = new bx_param_enum_c (BXP_FLOPPYA_TYPE,
- "floppya:type",
- "Type of floppy disk",
- floppy_type_names,
- BX_FLOPPY_NONE,
- BX_FLOPPY_NONE);
- bx_options.floppya.Otype->set_ask_format ("What type of floppy disk? [%s] ");
- bx_options.floppya.Ostatus = new bx_param_enum_c (BXP_FLOPPYA_STATUS,
- "Is floppya inserted",
- "Inserted or ejected",
- floppy_status_names,
- BX_INSERTED,
- BX_EJECTED);
- bx_options.floppya.Ostatus->set_ask_format ("Is the floppy inserted or ejected? [%s] ");
- bx_options.floppya.Opath->set_format ("%s");
- bx_options.floppya.Otype->set_format ("size=%s");
- bx_options.floppya.Ostatus->set_format ("%s");
- bx_param_c *floppya_init_list[] = {
- // if the order "path,type,status" changes, corresponding changes must
- // be made in gui/wxmain.cc, MyFrame::editFloppyConfig.
- bx_options.floppya.Opath,
- bx_options.floppya.Otype,
- bx_options.floppya.Ostatus,
- NULL
- };
- menu = new bx_list_c (BXP_FLOPPYA, "Floppy Disk 0", "All options for first floppy disk", floppya_init_list);
- menu->get_options ()->set (menu->SERIES_ASK);
- bx_options.floppya.Opath->set_handler (bx_param_string_handler);
- bx_options.floppya.Opath->set ("none");
- bx_options.floppya.Otype->set_handler (bx_param_handler);
- bx_options.floppya.Ostatus->set_handler (bx_param_handler);
-
- bx_options.floppyb.Opath = new bx_param_filename_c (BXP_FLOPPYB_PATH,
- "floppyb:path",
- "Pathname of second floppy image file or device.",
- "", BX_PATHNAME_LEN);
- bx_options.floppyb.Opath->set_ask_format ("Enter new filename, or 'none' for no disk: [%s] ");
- bx_options.floppyb.Opath->set_label ("Second floppy image/device");
- bx_options.floppyb.Odevtype = new bx_param_enum_c (BXP_FLOPPYB_DEVTYPE,
- "floppyb:devtype",
- "Type of floppy drive",
- floppy_type_names,
- BX_FLOPPY_NONE,
- BX_FLOPPY_NONE);
- bx_options.floppyb.Otype = new bx_param_enum_c (BXP_FLOPPYB_TYPE,
- "floppyb:type",
- "Type of floppy disk",
- floppy_type_names,
- BX_FLOPPY_NONE,
- BX_FLOPPY_NONE);
- bx_options.floppyb.Otype->set_ask_format ("What type of floppy disk? [%s] ");
- bx_options.floppyb.Ostatus = new bx_param_enum_c (BXP_FLOPPYB_STATUS,
- "Is floppyb inserted",
- "Inserted or ejected",
- floppy_status_names,
- BX_INSERTED,
- BX_EJECTED);
- bx_options.floppyb.Ostatus->set_ask_format ("Is the floppy inserted or ejected? [%s] ");
- bx_options.floppyb.Opath->set_format ("%s");
- bx_options.floppyb.Otype->set_format ("size=%s");
- bx_options.floppyb.Ostatus->set_format ("%s");
- bx_param_c *floppyb_init_list[] = {
- bx_options.floppyb.Opath,
- bx_options.floppyb.Otype,
- bx_options.floppyb.Ostatus,
- NULL
- };
- menu = new bx_list_c (BXP_FLOPPYB, "Floppy Disk 1", "All options for second floppy disk", floppyb_init_list);
- menu->get_options ()->set (menu->SERIES_ASK);
- bx_options.floppyb.Opath->set_handler (bx_param_string_handler);
- bx_options.floppyb.Opath->set ("none");
- bx_options.floppyb.Otype->set_handler (bx_param_handler);
- bx_options.floppyb.Ostatus->set_handler (bx_param_handler);
-
- // disk options
-
- // FIXME use descr and name
- char *s_atachannel[] = {
- "ATA channel 0",
- "ATA channel 1",
- "ATA channel 2",
- "ATA channel 3",
- };
- char *s_atadevice[4][2] = {
- { "First HD/CD on channel 0",
- "Second HD/CD on channel 0" },
- { "First HD/CD on channel 1",
- "Second HD/CD on channel 1" },
- { "First HD/CD on channel 2",
- "Second HD/CD on channel 2" },
- { "First HD/CD on channel 3",
- "Second HD/CD on channel 3" }
- };
- Bit16u ata_default_ioaddr1[BX_MAX_ATA_CHANNEL] = {
- 0x1f0, 0x170, 0x1e8, 0x168
- };
- Bit16u ata_default_ioaddr2[BX_MAX_ATA_CHANNEL] = {
- 0x3f0, 0x370, 0x3e0, 0x360
- };
- Bit8u ata_default_irq[BX_MAX_ATA_CHANNEL] = {
- 14, 15, 11, 9
- };
-
- bx_list_c *ata[BX_MAX_ATA_CHANNEL];
- bx_list_c *ata_menu[BX_MAX_ATA_CHANNEL];
-
- Bit8u channel;
- for (channel=0; channel<BX_MAX_ATA_CHANNEL; channel ++) {
-
- ata[channel] = new bx_list_c ((bx_id)(BXP_ATAx(channel)), s_atachannel[channel], s_atachannel[channel], 8);
- ata[channel]->get_options ()->set (bx_list_c::SERIES_ASK);
-
- ata[channel]->add (bx_options.ata[channel].Opresent = new bx_param_bool_c ((bx_id)(BXP_ATAx_PRESENT(channel)),
- "ata:present",
- "Controls whether ata channel is installed or not",
- 0));
-
- ata[channel]->add (bx_options.ata[channel].Oioaddr1 = new bx_param_num_c ((bx_id)(BXP_ATAx_IOADDR1(channel)),
- "ata:ioaddr1",
- "IO adress of ata command block",
- 0, 0xffff,
- ata_default_ioaddr1[channel]));
-
- ata[channel]->add (bx_options.ata[channel].Oioaddr2 = new bx_param_num_c ((bx_id)(BXP_ATAx_IOADDR2(channel)),
- "ata:ioaddr2",
- "IO adress of ata control block",
- 0, 0xffff,
- ata_default_ioaddr2[channel]));
-
- ata[channel]->add (bx_options.ata[channel].Oirq = new bx_param_num_c ((bx_id)(BXP_ATAx_IRQ(channel)),
- "ata:irq",
- "IRQ used by this ata channel",
- 0, 15,
- ata_default_irq[channel]));
-
- // all items in the ata[channel] menu depend on the present flag.
- // The menu list is complete, but a few dependent_list items will
- // be added later. Use clone() to make a copy of the dependent_list
- // so that it can be changed without affecting the menu.
- bx_options.ata[channel].Opresent->set_dependent_list (
- ata[channel]->clone());
-
- for (Bit8u slave=0; slave<2; slave++) {
-
- menu = bx_options.atadevice[channel][slave].Omenu = new bx_list_c ((bx_id)(BXP_ATAx_DEVICE(channel,slave)),
- s_atadevice[channel][slave],
- s_atadevice[channel][slave],
- BXP_PARAMS_PER_ATA_DEVICE + 1 );
- menu->get_options ()->set (menu->SERIES_ASK);
-
- menu->add (bx_options.atadevice[channel][slave].Opresent = new bx_param_bool_c ((bx_id)(BXP_ATAx_DEVICE_PRESENT(channel,slave)),
- "ata-device:present",
- "Controls whether ata device is installed or not",
- 0));
-
- menu->add (bx_options.atadevice[channel][slave].Otype = new bx_param_enum_c ((bx_id)(BXP_ATAx_DEVICE_TYPE(channel,slave)),
- "ata-device:type",
- "Type of ATA device (disk or cdrom)",
- atadevice_type_names,
- BX_ATA_DEVICE_DISK,
- BX_ATA_DEVICE_DISK));
-
- menu->add (bx_options.atadevice[channel][slave].Opath = new bx_param_filename_c ((bx_id)(BXP_ATAx_DEVICE_PATH(channel,slave)),
- "ata-device:path",
- "Pathname of the image or physical device (cdrom only)",
- "", BX_PATHNAME_LEN));
-
- menu->add (bx_options.atadevice[channel][slave].Omode = new bx_param_enum_c ((bx_id)(BXP_ATAx_DEVICE_MODE(channel,slave)),
- "ata-device:mode",
- "Mode of the ATA harddisk",
- atadevice_mode_names,
- BX_ATA_MODE_FLAT,
- BX_ATA_MODE_FLAT));
-
- menu->add (bx_options.atadevice[channel][slave].Ostatus = new bx_param_enum_c ((bx_id)(BXP_ATAx_DEVICE_STATUS(channel,slave)),
- "ata-device:status",
- "CD-ROM media status (inserted / ejected)",
- atadevice_status_names,
- BX_INSERTED,
- BX_EJECTED));
-
- menu->add (bx_options.atadevice[channel][slave].Ojournal = new bx_param_filename_c ((bx_id)(BXP_ATAx_DEVICE_JOURNAL(channel,slave)),
- "ata-device:journal",
- "Pathname of the journal file",
- "", BX_PATHNAME_LEN));
-
- menu->add (bx_options.atadevice[channel][slave].Ocylinders = new bx_param_num_c ((bx_id)(BXP_ATAx_DEVICE_CYLINDERS(channel,slave)),
- "ata-device:cylinders",
- "Number of cylinders",
- 0, 65535,
- 0));
- menu->add (bx_options.atadevice[channel][slave].Oheads = new bx_param_num_c ((bx_id)(BXP_ATAx_DEVICE_HEADS(channel,slave)),
- "ata-device:heads",
- "Number of heads",
- 0, 65535,
- 0));
- menu->add (bx_options.atadevice[channel][slave].Ospt = new bx_param_num_c ((bx_id)(BXP_ATAx_DEVICE_SPT(channel,slave)),
- "ata-device:spt",
- "Number of sectors per track",
- 0, 65535,
- 0));
-
- menu->add (bx_options.atadevice[channel][slave].Omodel = new bx_param_string_c ((bx_id)(BXP_ATAx_DEVICE_MODEL(channel,slave)),
- "ata-device:model",
- "String returned by the 'identify device' command",
- "Generic 1234", 40));
-
- menu->add (bx_options.atadevice[channel][slave].Obiosdetect = new bx_param_enum_c ((bx_id)(BXP_ATAx_DEVICE_BIOSDETECT(channel,slave)),
- "ata-device:biosdetect",
- "Type of bios detection",
- atadevice_biosdetect_names,
- BX_ATA_BIOSDETECT_AUTO,
- BX_ATA_BIOSDETECT_NONE));
-
- menu->add (bx_options.atadevice[channel][slave].Otranslation = new bx_param_enum_c ((bx_id)(BXP_ATAx_DEVICE_TRANSLATION(channel,slave)),
- "How the ata-disk translation is done by the bios",
- "Type of translation",
- atadevice_translation_names,
- BX_ATA_TRANSLATION_AUTO,
- BX_ATA_TRANSLATION_NONE));
-
- bx_options.atadevice[channel][slave].Opresent->set_dependent_list (
- menu->clone ());
- // the menu and all items on it depend on the Opresent flag
- bx_options.atadevice[channel][slave].Opresent->get_dependent_list()->add(menu);
- // the present flag depends on the ATA channel's present flag
- bx_options.ata[channel].Opresent->get_dependent_list()->add (
- bx_options.atadevice[channel][slave].Opresent);
- }
-
- // set up top level menu for ATA[i] controller configuration. This list
- // controls what will appear on the ATA configure dialog. It now
- // requests the USE_TAB_WINDOW display, which is implemented in wx.
- char buffer[32];
- sprintf (buffer, "Configure ATA%d", channel);
- ata_menu[channel] = new bx_list_c ((bx_id)(BXP_ATAx_MENU(channel)), strdup(buffer), "", 4);
- ata_menu[channel]->add (ata[channel]);
- ata_menu[channel]->add (bx_options.atadevice[channel][0].Omenu);
- ata_menu[channel]->add (bx_options.atadevice[channel][1].Omenu);
- ata_menu[channel]->get_options()->set (bx_list_c::USE_TAB_WINDOW);
- }
-
- // Enable first ata interface by default, disable the others.
- bx_options.ata[0].Opresent->set_initial_val(1);
-
- // now that the dependence relationships are established, call set() on
- // the ata device present params to set all enables correctly.
- for (i=0; i<BX_MAX_ATA_CHANNEL; i++)
- bx_options.ata[i].Opresent->set (i==0);
-
- for (channel=0; channel<BX_MAX_ATA_CHANNEL; channel ++) {
-
- bx_options.ata[channel].Opresent->set_ask_format ("Channel is enabled: [%s] ");
- bx_options.ata[channel].Oioaddr1->set_ask_format ("Enter new ioaddr1: [0x%x] ");
- bx_options.ata[channel].Oioaddr2->set_ask_format ("Enter new ioaddr2: [0x%x] ");
- bx_options.ata[channel].Oirq->set_ask_format ("Enter new IRQ: [%d] ");
-#if BX_WITH_WX
- bx_options.ata[channel].Opresent->set_label ("Enable this channel?");
- bx_options.ata[channel].Oioaddr1->set_label ("I/O Address 1:");
- bx_options.ata[channel].Oioaddr2->set_label ("I/O Address 2:");
- bx_options.ata[channel].Oirq->set_label ("IRQ:");
- bx_options.ata[channel].Oirq->set_options (bx_param_num_c::USE_SPIN_CONTROL);
-#else
- bx_options.ata[channel].Opresent->set_format ("enabled: %s");
- bx_options.ata[channel].Oioaddr1->set_format ("ioaddr1: 0x%x");
- bx_options.ata[channel].Oioaddr2->set_format ("ioaddr2: 0x%x");
- bx_options.ata[channel].Oirq->set_format ("irq: %d");
-#endif
- bx_options.ata[channel].Oioaddr1->set_base (16);
- bx_options.ata[channel].Oioaddr2->set_base (16);
-
- for (Bit8u slave=0; slave<2; slave++) {
-
- bx_options.atadevice[channel][slave].Opresent->set_ask_format (
- "Device is enabled: [%s] ");
- bx_options.atadevice[channel][slave].Otype->set_ask_format (
- "Enter type of ATA device, disk or cdrom: [%s] ");
- bx_options.atadevice[channel][slave].Omode->set_ask_format (
- "Enter mode of ATA device, (flat, concat, etc.): [%s] ");
- bx_options.atadevice[channel][slave].Opath->set_ask_format (
- "Enter new filename: [%s] ");
- bx_options.atadevice[channel][slave].Ocylinders->set_ask_format (
- "Enter number of cylinders: [%d] ");
- bx_options.atadevice[channel][slave].Oheads->set_ask_format (
- "Enter number of heads: [%d] ");
- bx_options.atadevice[channel][slave].Ospt->set_ask_format (
- "Enter number of sectors per track: [%d] ");
- bx_options.atadevice[channel][slave].Ostatus->set_ask_format (
- "Is the device inserted or ejected? [%s] ");
- bx_options.atadevice[channel][slave].Omodel->set_ask_format (
- "Enter new model name: [%s]");
- bx_options.atadevice[channel][slave].Otranslation->set_ask_format (
- "Enter translation type: [%s]");
- bx_options.atadevice[channel][slave].Obiosdetect->set_ask_format (
- "Enter bios detection type: [%s]");
- bx_options.atadevice[channel][slave].Ojournal->set_ask_format (
- "Enter path of journal file: [%s]");
-
-#if BX_WITH_WX
- bx_options.atadevice[channel][slave].Opresent->set_label (
- "Enable this device?");
- bx_options.atadevice[channel][slave].Otype->set_label (
- "Type of ATA device:");
- bx_options.atadevice[channel][slave].Omode->set_label (
- "Type of disk image:");
- bx_options.atadevice[channel][slave].Opath->set_label (
- "Path or physical device name:");
- bx_options.atadevice[channel][slave].Ocylinders->set_label (
- "Cylinders:");
- bx_options.atadevice[channel][slave].Oheads->set_label (
- "Heads:");
- bx_options.atadevice[channel][slave].Ospt->set_label (
- "Sectors per track:");
- bx_options.atadevice[channel][slave].Ostatus->set_label (
- "Inserted?");
- bx_options.atadevice[channel][slave].Omodel->set_label (
- "Model name:");
- bx_options.atadevice[channel][slave].Otranslation->set_label (
- "Translation type:");
- bx_options.atadevice[channel][slave].Obiosdetect->set_label (
- "BIOS Detection:");
- bx_options.atadevice[channel][slave].Ojournal->set_label (
- "Path of journal file:");
-#else
- bx_options.atadevice[channel][slave].Opresent->set_format ("enabled: %s");
- bx_options.atadevice[channel][slave].Otype->set_format ("type %s");
- bx_options.atadevice[channel][slave].Omode->set_format ("mode %s");
- bx_options.atadevice[channel][slave].Opath->set_format ("path '%s'");
- bx_options.atadevice[channel][slave].Ocylinders->set_format ("%d cylinders");
- bx_options.atadevice[channel][slave].Oheads->set_format ("%d heads");
- bx_options.atadevice[channel][slave].Ospt->set_format ("%d sectors/track");
- bx_options.atadevice[channel][slave].Ostatus->set_format ("%s");
- bx_options.atadevice[channel][slave].Omodel->set_format ("model '%s'");
- bx_options.atadevice[channel][slave].Otranslation->set_format ("translation '%s'");
- bx_options.atadevice[channel][slave].Obiosdetect->set_format ("biosdetect '%s'");
- bx_options.atadevice[channel][slave].Ojournal->set_format ("journal is '%s'");
-#endif
-
- bx_options.atadevice[channel][slave].Otype->set_handler (bx_param_handler);
- bx_options.atadevice[channel][slave].Omode->set_handler (bx_param_handler);
- bx_options.atadevice[channel][slave].Ostatus->set_handler (bx_param_handler);
- bx_options.atadevice[channel][slave].Opath->set_handler (bx_param_string_handler);
-
- // Set the enable_hanlders
- bx_options.atadevice[channel][slave].Ojournal->set_enable_handler (bx_param_enable_handler);
- bx_options.atadevice[channel][slave].Ostatus->set_enable_handler (bx_param_enable_handler);
-
- }
- }
-
- bx_options.OnewHardDriveSupport = new bx_param_bool_c (BXP_NEWHARDDRIVESUPPORT,
- "New hard drive support",
- "Enables new features found on newer hard drives.",
- 1);
-
- bx_options.Obootdrive = new bx_param_enum_c (BXP_BOOTDRIVE,
- "bootdrive",
- "Boot A, C or CD",
- floppy_bootdisk_names,
- BX_BOOT_FLOPPYA,
- BX_BOOT_FLOPPYA);
- bx_options.Obootdrive->set_format ("Boot from: %s drive");
- bx_options.Obootdrive->set_ask_format ("Boot from floppy drive, hard drive or cdrom ? [%s] ");
-
- bx_options.OfloppySigCheck = new bx_param_bool_c (BXP_FLOPPYSIGCHECK,
- "Skip Floppy Boot Signature Check",
- "Skips check for the 0xaa55 signature on floppy boot device.",
- 0);
-
- // disk menu
- bx_param_c *disk_menu_init_list[] = {
- SIM->get_param (BXP_FLOPPYA),
- SIM->get_param (BXP_FLOPPYB),
- SIM->get_param (BXP_ATA0),
- SIM->get_param (BXP_ATA0_MASTER),
- SIM->get_param (BXP_ATA0_SLAVE),
-#if BX_MAX_ATA_CHANNEL>1
- SIM->get_param (BXP_ATA1),
- SIM->get_param (BXP_ATA1_MASTER),
- SIM->get_param (BXP_ATA1_SLAVE),
-#endif
-#if BX_MAX_ATA_CHANNEL>2
- SIM->get_param (BXP_ATA2),
- SIM->get_param (BXP_ATA2_MASTER),
- SIM->get_param (BXP_ATA2_SLAVE),
-#endif
-#if BX_MAX_ATA_CHANNEL>3
- SIM->get_param (BXP_ATA3),
- SIM->get_param (BXP_ATA3_MASTER),
- SIM->get_param (BXP_ATA3_SLAVE),
-#endif
- SIM->get_param (BXP_NEWHARDDRIVESUPPORT),
- SIM->get_param (BXP_BOOTDRIVE),
- SIM->get_param (BXP_FLOPPYSIGCHECK),
- NULL
- };
- menu = new bx_list_c (BXP_MENU_DISK, "Bochs Disk Options", "diskmenu", disk_menu_init_list);
- menu->get_options ()->set (menu->SHOW_PARENT);
-
- // memory options menu
- bx_options.memory.Osize = new bx_param_num_c (BXP_MEM_SIZE,
- "megs",
- "Amount of RAM in megabytes",
- 1, BX_MAX_BIT32U,
- BX_DEFAULT_MEM_MEGS);
- bx_options.memory.Osize->set_ask_format ("Enter memory size (MB): [%d] ");
-#if BX_WITH_WX
- bx_options.memory.Osize->set_label ("Memory size (megabytes)");
- bx_options.memory.Osize->set_options (bx_param_num_c::USE_SPIN_CONTROL);
-#else
- bx_options.memory.Osize->set_format ("Memory size in megabytes: %d");
-#endif
-
- // initialize serial and parallel port options
-#define PAR_SER_INIT_LIST_MAX \
- ((BXP_PARAMS_PER_PARALLEL_PORT * BX_N_PARALLEL_PORTS) \
- + (BXP_PARAMS_PER_SERIAL_PORT * BX_N_SERIAL_PORTS) \
- + (BXP_PARAMS_PER_USB_HUB * BX_N_USB_HUBS))
- bx_param_c *par_ser_init_list[1+PAR_SER_INIT_LIST_MAX];
- bx_param_c **par_ser_ptr = &par_ser_init_list[0];
-
- // parallel ports
- for (i=0; i<BX_N_PARALLEL_PORTS; i++) {
- sprintf (name, "Enable parallel port #%d", i+1);
- sprintf (descr, "Controls whether parallel port #%d is installed or not", i+1);
- bx_options.par[i].Oenabled = new bx_param_bool_c (
- BXP_PARPORTx_ENABLED(i+1),
- strdup(name),
- strdup(descr),
- (i==0)? 1 : 0); // only enable #1 by default
- sprintf (name, "Parallel port #%d output file", i+1);
- sprintf (descr, "Data written to parport#%d by the guest OS is written to this file", i+1);
- bx_options.par[i].Ooutfile = new bx_param_filename_c (
- BXP_PARPORTx_OUTFILE(i+1),
- strdup(name),
- strdup(descr),
- "", BX_PATHNAME_LEN);
- deplist = new bx_list_c (BXP_NULL, 1);
- deplist->add (bx_options.par[i].Ooutfile);
- bx_options.par[i].Oenabled->set_dependent_list (deplist);
- // add to menu
- *par_ser_ptr++ = bx_options.par[i].Oenabled;
- *par_ser_ptr++ = bx_options.par[i].Ooutfile;
- }
-
- // serial ports
- for (i=0; i<BX_N_SERIAL_PORTS; i++) {
- // options for COM port
- sprintf (name, "Enable serial port #%d (COM%d)", i+1, i+1);
- sprintf (descr, "Controls whether COM%d is installed or not", i+1);
- bx_options.com[i].Oenabled = new bx_param_bool_c (
- BXP_COMx_ENABLED(i+1),
- strdup(name),
- strdup(descr),
- (i==0)?1 : 0); // only enable the first by default
- sprintf (name, "Pathname of the serial device for COM%d", i+1);
- sprintf (descr, "The path can be a real serial device or a pty (X/Unix only)");
- bx_options.com[i].Odev = new bx_param_filename_c (
- BXP_COMx_PATH(i+1),
- strdup(name),
- strdup(descr),
- "", BX_PATHNAME_LEN);
- deplist = new bx_list_c (BXP_NULL, 1);
- deplist->add (bx_options.com[i].Odev);
- bx_options.com[i].Oenabled->set_dependent_list (deplist);
- // add to menu
- *par_ser_ptr++ = bx_options.com[i].Oenabled;
- *par_ser_ptr++ = bx_options.com[i].Odev;
- }
-
- // usb hubs
- for (i=0; i<BX_N_USB_HUBS; i++) {
- // options for USB hub
- sprintf (name, "usb%d:enabled", i+1);
- sprintf (descr, "Controls whether USB%d is installed or not", i+1);
- sprintf (label, "Enable usb hub #%d (USB%d)", i+1, i+1);
- bx_options.usb[i].Oenabled = new bx_param_bool_c (
- BXP_USBx_ENABLED(i+1),
- strdup(name),
- strdup(descr),
- (i==0)?1 : 0); // only enable the first by default
- bx_options.usb[i].Oioaddr = new bx_param_num_c (
- BXP_USBx_IOADDR(i+1),
- "usb:ioaddr",
- "I/O base adress of USB hub",
- 0, 0xffe0,
- (i==0)?0xff80 : 0);
- bx_options.usb[i].Oirq = new bx_param_num_c (
- BXP_USBx_IRQ(i+1),
- "usb:irq",
- "IRQ used by USB hub",
- 0, 15,
- (i==0)?10 : 0);
- deplist = new bx_list_c (BXP_NULL, 2);
- deplist->add (bx_options.usb[i].Oioaddr);
- deplist->add (bx_options.usb[i].Oirq);
- bx_options.usb[i].Oenabled->set_dependent_list (deplist);
- // add to menu
- *par_ser_ptr++ = bx_options.usb[i].Oenabled;
- *par_ser_ptr++ = bx_options.usb[i].Oioaddr;
- *par_ser_ptr++ = bx_options.usb[i].Oirq;
-
- bx_options.usb[i].Oioaddr->set_ask_format ("Enter new ioaddr: [0x%x] ");
- bx_options.usb[i].Oioaddr->set_label ("I/O Address");
- bx_options.usb[i].Oioaddr->set_base (16);
- bx_options.usb[i].Oenabled->set_label (strdup(label));
- bx_options.usb[i].Oirq->set_label ("USB IRQ");
- bx_options.usb[i].Oirq->set_options (bx_param_num_c::USE_SPIN_CONTROL);
- }
- // add final NULL at the end, and build the menu
- *par_ser_ptr = NULL;
- menu = new bx_list_c (BXP_MENU_SERIAL_PARALLEL,
- "Serial and Parallel Port Options",
- "serial_parallel_menu",
- par_ser_init_list);
- menu->get_options ()->set (menu->SHOW_PARENT);
-
- bx_options.rom.Opath = new bx_param_filename_c (BXP_ROM_PATH,
- "romimage",
- "Pathname of ROM image to load",
- "", BX_PATHNAME_LEN);
- bx_options.rom.Opath->set_format ("Name of ROM BIOS image: %s");
- bx_options.rom.Oaddress = new bx_param_num_c (BXP_ROM_ADDRESS,
- "romaddr",
- "The address at which the ROM image should be loaded",
- 0, BX_MAX_BIT32U,
- 0xf0000);
- bx_options.rom.Oaddress->set_base (16);
-#if BX_WITH_WX
- bx_options.rom.Opath->set_label ("ROM BIOS image");
- bx_options.rom.Oaddress->set_label ("ROM BIOS address");
-#else
- bx_options.rom.Oaddress->set_format ("ROM BIOS address: 0x%05x");
-#endif
-
- bx_options.optrom[0].Opath = new bx_param_filename_c (BXP_OPTROM1_PATH,
- "optional romimage #1",
- "Pathname of optional ROM image #1 to load",
- "", BX_PATHNAME_LEN);
- bx_options.optrom[0].Opath->set_format ("Name of optional ROM image #1 : %s");
- bx_options.optrom[0].Oaddress = new bx_param_num_c (BXP_OPTROM1_ADDRESS,
- "optional romaddr #1",
- "The address at which the optional ROM image #1 should be loaded",
- 0, BX_MAX_BIT32U,
- 0);
- bx_options.optrom[0].Oaddress->set_base (16);
-#if BX_WITH_WX
- bx_options.optrom[0].Opath->set_label ("Optional ROM image #1");
- bx_options.optrom[0].Oaddress->set_label ("Address");
-#else
- bx_options.optrom[0].Oaddress->set_format ("optional ROM #1 address: 0x%05x");
-#endif
-
- bx_options.optrom[1].Opath = new bx_param_filename_c (BXP_OPTROM2_PATH,
- "optional romimage #2",
- "Pathname of optional ROM image #2 to load",
- "", BX_PATHNAME_LEN);
- bx_options.optrom[1].Opath->set_format ("Name of optional ROM image #2 : %s");
- bx_options.optrom[1].Oaddress = new bx_param_num_c (BXP_OPTROM2_ADDRESS,
- "optional romaddr #2",
- "The address at which the optional ROM image #2 should be loaded",
- 0, BX_MAX_BIT32U,
- 0);
- bx_options.optrom[1].Oaddress->set_base (16);
-#if BX_WITH_WX
- bx_options.optrom[1].Opath->set_label ("Optional ROM image #2");
- bx_options.optrom[1].Oaddress->set_label ("Address");
-#else
- bx_options.optrom[1].Oaddress->set_format ("optional ROM #2 address: 0x%05x");
-#endif
-
- bx_options.optrom[2].Opath = new bx_param_filename_c (BXP_OPTROM3_PATH,
- "optional romimage #3",
- "Pathname of optional ROM image #3 to load",
- "", BX_PATHNAME_LEN);
- bx_options.optrom[2].Opath->set_format ("Name of optional ROM image #3 : %s");
- bx_options.optrom[2].Oaddress = new bx_param_num_c (BXP_OPTROM3_ADDRESS,
- "optional romaddr #3",
- "The address at which the optional ROM image #3 should be loaded",
- 0, BX_MAX_BIT32U,
- 0);
- bx_options.optrom[2].Oaddress->set_base (16);
-#if BX_WITH_WX
- bx_options.optrom[2].Opath->set_label ("Optional ROM image #3");
- bx_options.optrom[2].Oaddress->set_label ("Address");
-#else
- bx_options.optrom[2].Oaddress->set_format ("optional ROM #3 address: 0x%05x");
-#endif
-
- bx_options.optrom[3].Opath = new bx_param_filename_c (BXP_OPTROM4_PATH,
- "optional romimage #4",
- "Pathname of optional ROM image #4 to load",
- "", BX_PATHNAME_LEN);
- bx_options.optrom[3].Opath->set_format ("Name of optional ROM image #4 : %s");
- bx_options.optrom[3].Oaddress = new bx_param_num_c (BXP_OPTROM4_ADDRESS,
- "optional romaddr #4",
- "The address at which the optional ROM image #4 should be loaded",
- 0, BX_MAX_BIT32U,
- 0);
- bx_options.optrom[3].Oaddress->set_base (16);
-#if BX_WITH_WX
- bx_options.optrom[3].Opath->set_label ("Optional ROM image #4");
- bx_options.optrom[3].Oaddress->set_label ("Address");
-#else
- bx_options.optrom[3].Oaddress->set_format ("optional ROM #4 address: 0x%05x");
-#endif
-
- bx_options.vgarom.Opath = new bx_param_filename_c (BXP_VGA_ROM_PATH,
- "vgaromimage",
- "Pathname of VGA ROM image to load",
- "", BX_PATHNAME_LEN);
- bx_options.vgarom.Opath->set_format ("Name of VGA BIOS image: %s");
-#if BX_WITH_WX
- bx_options.vgarom.Opath->set_label ("VGA BIOS image");
-#endif
- bx_param_c *memory_init_list[] = {
- bx_options.memory.Osize,
- bx_options.vgarom.Opath,
- bx_options.rom.Opath,
- bx_options.rom.Oaddress,
- bx_options.optrom[0].Opath,
- bx_options.optrom[0].Oaddress,
- bx_options.optrom[1].Opath,
- bx_options.optrom[1].Oaddress,
- bx_options.optrom[2].Opath,
- bx_options.optrom[2].Oaddress,
- bx_options.optrom[3].Opath,
- bx_options.optrom[3].Oaddress,
- NULL
- };
- menu = new bx_list_c (BXP_MENU_MEMORY, "Bochs Memory Options", "memmenu", memory_init_list);
- menu->get_options ()->set (menu->SHOW_PARENT);
-
- // interface
- bx_options.Ovga_update_interval = new bx_param_num_c (BXP_VGA_UPDATE_INTERVAL,
- "VGA Update Interval",
- "Number of microseconds between VGA updates",
- 1, BX_MAX_BIT32U,
- 30000);
- bx_options.Ovga_update_interval->set_handler (bx_param_handler);
- bx_options.Ovga_update_interval->set_runtime_param (1);
- bx_options.Ovga_update_interval->set_ask_format ("Type a new value for VGA update interval: [%d] ");
- bx_options.Omouse_enabled = new bx_param_bool_c (BXP_MOUSE_ENABLED,
- "Enable the mouse",
- "Controls whether the mouse sends events to the guest. The hardware emulation is always enabled.",
- 0);
- bx_options.Omouse_enabled->set_handler (bx_param_handler);
- bx_options.Omouse_enabled->set_runtime_param (1);
- bx_options.Oips = new bx_param_num_c (BXP_IPS,
- "Emulated instructions per second (IPS)",
- "Emulated instructions per second, used to calibrate bochs emulated time with wall clock time.",
- 1, BX_MAX_BIT32U,
- 500000);
- bx_options.Otext_snapshot_check = new bx_param_bool_c (BXP_TEXT_SNAPSHOT_CHECK,
- "Enable panic for use in bochs testing",
- "Enable panic when text on screen matches snapchk.txt.\nUseful for regression testing.\nIn win32, turns off CR/LF in snapshots and cuts.",
- 0);
- bx_options.Oprivate_colormap = new bx_param_bool_c (BXP_PRIVATE_COLORMAP,
- "Use a private colormap",
- "Request that the GUI create and use it's own non-shared colormap. This colormap will be used when in the bochs window. If not enabled, a shared colormap scheme may be used. Not implemented on all GUI's.",
- 0);
-#if BX_WITH_AMIGAOS
- bx_options.Ofullscreen = new bx_param_bool_c (BXP_FULLSCREEN,
- "Use full screen mode",
- "When enabled, bochs occupies the whole screen instead of just a window.",
- 0);
- bx_options.Oscreenmode = new bx_param_string_c (BXP_SCREENMODE,
- "Screen mode name",
- "Screen mode name",
- "", BX_PATHNAME_LEN);
- bx_options.Oscreenmode->set_handler (bx_param_string_handler);
-#endif
- static char *config_interface_list[] = {
- "textconfig",
-#if BX_WITH_WX
- "wx",
-#endif
- NULL
- };
- bx_options.Osel_config = new bx_param_enum_c (
- BXP_SEL_CONFIG_INTERFACE,
- "Configuration interface",
- "Select configuration interface",
- config_interface_list,
- 0,
- 0);
- bx_options.Osel_config->set_by_name (BX_DEFAULT_CONFIG_INTERFACE);
- bx_options.Osel_config->set_ask_format ("Choose which configuration interface to use: [%s] ");
- // this is a list of gui libraries that are known to be available at
- // compile time. The one that is listed first will be the default,
- // which is used unless the user overrides it on the command line or
- // in a configuration file.
- static char *display_library_list[] = {
-#if BX_WITH_X11
- "x",
-#endif
-#if BX_WITH_WIN32
- "win32",
-#endif
-#if BX_WITH_CARBON
- "carbon",
-#endif
-#if BX_WITH_BEOS
- "beos",
-#endif
-#if BX_WITH_MACOS
- "macos",
-#endif
-#if BX_WITH_AMIGAOS
- "amigaos",
-#endif
-#if BX_WITH_SDL
- "sdl",
-#endif
-#if BX_WITH_SVGA
- "svga",
-#endif
-#if BX_WITH_TERM
- "term",
-#endif
-#if BX_WITH_RFB
- "rfb",
-#endif
-#if BX_WITH_WX
- "wx",
-#endif
-#if BX_WITH_NOGUI
- "nogui",
-#endif
- NULL
- };
- bx_options.Osel_displaylib = new bx_param_enum_c (BXP_SEL_DISPLAY_LIBRARY,
- "VGA Display Library",
- "Select VGA Display Library",
- display_library_list,
- 0,
- 0);
- bx_options.Osel_displaylib->set_by_name (BX_DEFAULT_DISPLAY_LIBRARY);
- bx_options.Osel_displaylib->set_ask_format ("Choose which library to use for the Bochs display: [%s] ");
- bx_param_c *interface_init_list[] = {
- bx_options.Osel_config,
- bx_options.Osel_displaylib,
- bx_options.Ovga_update_interval,
- bx_options.Omouse_enabled,
- bx_options.Oips,
- bx_options.Oprivate_colormap,
-#if BX_WITH_AMIGAOS
- bx_options.Ofullscreen,
- bx_options.Oscreenmode,
-#endif
- NULL
- };
- menu = new bx_list_c (BXP_MENU_INTERFACE, "Bochs Interface Menu", "intfmenu", interface_init_list);
- menu->get_options ()->set (menu->SHOW_PARENT);
-
- // NE2K options
- bx_options.ne2k.Opresent = new bx_param_bool_c (BXP_NE2K_PRESENT,
- "Enable NE2K NIC emulation",
- "Enables the NE2K NIC emulation",
- 0);
- bx_options.ne2k.Oioaddr = new bx_param_num_c (BXP_NE2K_IOADDR,
- "NE2K I/O Address",
- "I/O base address of the emulated NE2K device",
- 0, 0xffff,
- 0x240);
- bx_options.ne2k.Oioaddr->set_base (16);
- bx_options.ne2k.Oirq = new bx_param_num_c (BXP_NE2K_IRQ,
- "NE2K Interrupt",
- "IRQ used by the NE2K device",
- 0, 15,
- 9);
- bx_options.ne2k.Oirq->set_options (bx_param_num_c::USE_SPIN_CONTROL);
- bx_options.ne2k.Omacaddr = new bx_param_string_c (BXP_NE2K_MACADDR,
- "MAC Address",
- "MAC address of the NE2K device. Don't use an address of a machine on your net.",
- "\xfe\xfd\xde\xad\xbe\xef", 6);
- bx_options.ne2k.Omacaddr->get_options ()->set (bx_options.ne2k.Omacaddr->RAW_BYTES);
- bx_options.ne2k.Omacaddr->set_separator (':');
- static char *eth_module_list[] = {
- "null",
-#if defined(ETH_LINUX)
- "linux",
-#endif
-#if HAVE_ETHERTAP
- "tap",
-#endif
-#if HAVE_TUNTAP
- "tuntap",
-#endif
-#if defined(ETH_WIN32)
- "win32",
-#endif
-#if defined(ETH_FBSD)
- "fbsd",
-#endif
-#ifdef ETH_ARPBACK
- "arpback",
-#endif
- NULL
- };
- bx_options.ne2k.Oethmod = new bx_param_enum_c (BXP_NE2K_ETHMOD,
- "Ethernet module",
- "Module used for the connection to the real net.",
- eth_module_list,
- 0,
- 0);
- bx_options.ne2k.Oethmod->set_by_name ("null");
- bx_options.ne2k.Oethdev = new bx_param_string_c (BXP_NE2K_ETHDEV,
- "Ethernet device",
- "Device used for the connection to the real net. This is only valid if an ethernet module other than 'null' is used.",
- "xl0", BX_PATHNAME_LEN);
- bx_options.ne2k.Oscript = new bx_param_string_c (BXP_NE2K_SCRIPT,
- "Device configuration script",
- "Name of the script that is executed after Bochs initializes the network interface (optional).",
- "none", BX_PATHNAME_LEN);
-#if !BX_WITH_WX
- bx_options.ne2k.Oscript->set_ask_format ("Enter new script name, or 'none': [%s] ");
-#endif
- bx_param_c *ne2k_init_list[] = {
- bx_options.ne2k.Opresent,
- bx_options.ne2k.Oioaddr,
- bx_options.ne2k.Oirq,
- bx_options.ne2k.Omacaddr,
- bx_options.ne2k.Oethmod,
- bx_options.ne2k.Oethdev,
- bx_options.ne2k.Oscript,
- NULL
- };
- menu = new bx_list_c (BXP_NE2K, "NE2K Configuration", "", ne2k_init_list);
- menu->get_options ()->set (menu->SHOW_PARENT);
- bx_param_c **ne2k_dependent_list = &ne2k_init_list[1];
- bx_options.ne2k.Opresent->set_dependent_list (
- new bx_list_c (BXP_NULL, "", "", ne2k_dependent_list));
- bx_options.ne2k.Opresent->set_handler (bx_param_handler);
- bx_options.ne2k.Opresent->set (0);
-
- // SB16 options
- bx_options.sb16.Opresent = new bx_param_bool_c (BXP_SB16_PRESENT,
- "Enable SB16 emulation",
- "Enables the SB16 emulation",
- 0);
- bx_options.sb16.Omidifile = new bx_param_filename_c (BXP_SB16_MIDIFILE,
- "MIDI file",
- "The filename is where the MIDI data is sent. This can be device or just a file.",
- "", BX_PATHNAME_LEN);
- bx_options.sb16.Owavefile = new bx_param_filename_c (BXP_SB16_WAVEFILE,
- "Wave file",
- "This is the device/file where the wave output is stored",
- "", BX_PATHNAME_LEN);
- bx_options.sb16.Ologfile = new bx_param_filename_c (BXP_SB16_LOGFILE,
- "Log file",
- "The file to write the SB16 emulator messages to.",
- "", BX_PATHNAME_LEN);
- bx_options.sb16.Omidimode = new bx_param_num_c (BXP_SB16_MIDIMODE,
- "Midi mode",
- "Controls the MIDI output format.",
- 0, 3,
- 0);
- bx_options.sb16.Owavemode = new bx_param_num_c (BXP_SB16_WAVEMODE,
- "Wave mode",
- "Controls the wave output format.",
- 0, 3,
- 0);
- bx_options.sb16.Ologlevel = new bx_param_num_c (BXP_SB16_LOGLEVEL,
- "Log mode",
- "Controls how verbose the SB16 emulation is (0 = no log, 5 = all errors and infos).",
- 0, 5,
- 0);
- bx_options.sb16.Odmatimer = new bx_param_num_c (BXP_SB16_DMATIMER,
- "DMA timer",
- "Microseconds per second for a DMA cycle.",
- 0, BX_MAX_BIT32U,
- 0);
-
-#if BX_WITH_WX
- bx_options.sb16.Omidimode->set_options (bx_param_num_c::USE_SPIN_CONTROL);
- bx_options.sb16.Owavemode->set_options (bx_param_num_c::USE_SPIN_CONTROL);
- bx_options.sb16.Ologlevel->set_options (bx_param_num_c::USE_SPIN_CONTROL);
-#endif
- bx_param_c *sb16_init_list[] = {
- bx_options.sb16.Opresent,
- bx_options.sb16.Omidimode,
- bx_options.sb16.Omidifile,
- bx_options.sb16.Owavemode,
- bx_options.sb16.Owavefile,
- bx_options.sb16.Ologlevel,
- bx_options.sb16.Ologfile,
- bx_options.sb16.Odmatimer,
- NULL
- };
- menu = new bx_list_c (BXP_SB16, "SB16 Configuration", "", sb16_init_list);
- menu->get_options ()->set (menu->SHOW_PARENT);
- // sb16_dependent_list is a null-terminated list including all the
- // sb16 fields except for the "present" field. These will all be enabled/
- // disabled according to the value of the present field.
- bx_param_c **sb16_dependent_list = &sb16_init_list[1];
- bx_options.sb16.Opresent->set_dependent_list (
- new bx_list_c (BXP_NULL, "", "", sb16_dependent_list));
-
- bx_options.log.Ofilename = new bx_param_filename_c (BXP_LOG_FILENAME,
- "Log filename",
- "Pathname of bochs log file",
- "-", BX_PATHNAME_LEN);
- bx_options.log.Ofilename->set_ask_format ("Enter log filename: [%s] ");
-
- bx_options.log.Oprefix = new bx_param_string_c (BXP_LOG_PREFIX,
- "Log output prefix",
- "Prefix prepended to log output",
- "%t%e%d", BX_PATHNAME_LEN);
- bx_options.log.Oprefix->set_ask_format ("Enter log prefix: [%s] ");
-
- bx_options.log.Odebugger_filename = new bx_param_filename_c (BXP_DEBUGGER_LOG_FILENAME,
- "Debugger Log filename",
- "Pathname of debugger log file",
- "-", BX_PATHNAME_LEN);
- bx_options.log.Odebugger_filename->set_ask_format ("Enter debugger log filename: [%s] ");
-
- // loader
- bx_options.load32bitOSImage.OwhichOS = new bx_param_enum_c (BXP_LOAD32BITOS_WHICH,
- "Which operating system?",
- "Which OS to boot",
- loader_os_names,
-#ifdef BX_USE_VMX
- Load32bitOSLinux,
-#else
- Load32bitOSNone,
-#endif
- Load32bitOSNone);
- bx_options.load32bitOSImage.Opath = new bx_param_filename_c (BXP_LOAD32BITOS_PATH,
- "Pathname of OS to load",
- "Pathname of the 32-bit OS to load",
- "", BX_PATHNAME_LEN);
- bx_options.load32bitOSImage.Oiolog = new bx_param_filename_c (BXP_LOAD32BITOS_IOLOG,
- "Pathname of I/O log file",
- "I/O logfile used for initializing the hardware",
- "", BX_PATHNAME_LEN);
- bx_options.load32bitOSImage.Oinitrd = new bx_param_filename_c (BXP_LOAD32BITOS_INITRD,
- "Pathname of initrd",
- "Pathname of the initial ramdisk",
- "", BX_PATHNAME_LEN);
- bx_param_c *loader_init_list[] = {
- bx_options.load32bitOSImage.OwhichOS,
- bx_options.load32bitOSImage.Opath,
- bx_options.load32bitOSImage.Oiolog,
- bx_options.load32bitOSImage.Oinitrd,
- NULL
- };
- bx_options.load32bitOSImage.OwhichOS->set_format ("os=%s");
- bx_options.load32bitOSImage.Opath->set_format ("path=%s");
- bx_options.load32bitOSImage.Oiolog->set_format ("iolog=%s");
- bx_options.load32bitOSImage.Oinitrd->set_format ("initrd=%s");
- bx_options.load32bitOSImage.OwhichOS->set_ask_format ("Enter OS to load: [%s] ");
- bx_options.load32bitOSImage.Opath->set_ask_format ("Enter pathname of OS: [%s]");
- bx_options.load32bitOSImage.Oiolog->set_ask_format ("Enter pathname of I/O log: [%s] ");
- bx_options.load32bitOSImage.Oinitrd->set_ask_format ("Enter pathname of initrd: [%s] ");
- menu = new bx_list_c (BXP_LOAD32BITOS, "32-bit OS Loader", "", loader_init_list);
- menu->get_options ()->set (menu->SERIES_ASK);
- bx_options.load32bitOSImage.OwhichOS->set_handler (bx_param_handler);
-#ifdef BX_USE_VMX
- bx_options.load32bitOSImage.OwhichOS->set (Load32bitOSLinux);
-#else
- bx_options.load32bitOSImage.OwhichOS->set (Load32bitOSNone);
-#endif
-
- // clock
- bx_options.clock.Otime0 = new bx_param_num_c (BXP_CLOCK_TIME0,
- "clock:time0",
- "Initial time for Bochs CMOS clock, used if you really want two runs to be identical",
- 0, BX_MAX_BIT32U,
- BX_CLOCK_TIME0_LOCAL);
- bx_options.clock.Osync = new bx_param_enum_c (BXP_CLOCK_SYNC,
- "clock:sync",
- "Host to guest time synchronization method",
- clock_sync_names,
- BX_CLOCK_SYNC_NONE,
- BX_CLOCK_SYNC_NONE);
- bx_param_c *clock_init_list[] = {
- bx_options.clock.Osync,
- bx_options.clock.Otime0,
- NULL
- };
-#if !BX_WITH_WX
- bx_options.clock.Osync->set_format ("sync=%s");
- bx_options.clock.Otime0->set_format ("initial time=%d");
-#endif
- bx_options.clock.Otime0->set_ask_format ("Enter Initial CMOS time (1:localtime, 2:utc, other:time in seconds): [%d] ");
- bx_options.clock.Osync->set_ask_format ("Enter Synchronisation method: [%s] ");
- bx_options.clock.Otime0->set_label ("Initial CMOS time for Bochs\n(1:localtime, 2:utc, other:time in seconds)");
- bx_options.clock.Osync->set_label ("Synchronisation method");
- menu = new bx_list_c (BXP_CLOCK, "Clock parameters", "", clock_init_list);
- menu->get_options ()->set (menu->SERIES_ASK);
-
- // other
- bx_options.Okeyboard_serial_delay = new bx_param_num_c (BXP_KBD_SERIAL_DELAY,
- "Keyboard serial delay",
- "Approximate time in microseconds that it takes one character to be transfered from the keyboard to controller over the serial path.",
- 1, BX_MAX_BIT32U,
- 20000);
- bx_options.Okeyboard_paste_delay = new bx_param_num_c (BXP_KBD_PASTE_DELAY,
- "Keyboard paste delay",
- "Approximate time in microseconds between attemps to paste characters to the keyboard controller.",
- 1000, BX_MAX_BIT32U,
- 100000);
- bx_options.Okeyboard_paste_delay->set_handler (bx_param_handler);
- bx_options.Okeyboard_paste_delay->set_runtime_param (1);
- bx_options.Ofloppy_command_delay = new bx_param_num_c (BXP_FLOPPY_CMD_DELAY,
- "Floppy command delay",
- "Time in microseconds to wait before completing some floppy commands such as read/write/seek/etc, which normally have a delay associated. This used to be hardwired to 50,000 before.",
- 1, BX_MAX_BIT32U,
- 50000);
- bx_options.Oi440FXSupport = new bx_param_bool_c (BXP_I440FX_SUPPORT,
- "PCI i440FX Support",
- "Controls whether to emulate the i440FX PCI chipset",
- 0);
- bx_options.cmos.OcmosImage = new bx_param_bool_c (BXP_CMOS_IMAGE,
- "Use a CMOS image",
- "Controls the usage of a CMOS image",
- 0);
- bx_options.cmos.Opath = new bx_param_filename_c (BXP_CMOS_PATH,
- "Pathname of CMOS image",
- "Pathname of CMOS image",
- "", BX_PATHNAME_LEN);
- deplist = new bx_list_c (BXP_NULL, 1);
- deplist->add (bx_options.cmos.Opath);
- bx_options.cmos.OcmosImage->set_dependent_list (deplist);
-
- // Keyboard mapping
- bx_options.keyboard.OuseMapping = new bx_param_bool_c(BXP_KEYBOARD_USEMAPPING,
- "Use keyboard mapping",
- "Controls whether to use the keyboard mapping feature",
- 0);
- bx_options.keyboard.Okeymap = new bx_param_filename_c (BXP_KEYBOARD_MAP,
- "Keymap filename",
- "Pathname of the keymap file used",
- "", BX_PATHNAME_LEN);
- deplist = new bx_list_c (BXP_NULL, 1);
- deplist->add (bx_options.keyboard.Okeymap);
- bx_options.keyboard.OuseMapping->set_dependent_list (deplist);
-
- // Keyboard type
- bx_options.Okeyboard_type = new bx_param_enum_c (BXP_KBD_TYPE,
- "Keyboard type",
- "Keyboard type reported by the 'identify keyboard' command",
- keyboard_type_names,
- BX_KBD_MF_TYPE,
- BX_KBD_XT_TYPE);
- bx_options.Okeyboard_type->set_ask_format ("Enter keyboard type: [%s] ");
-
- // Userbutton shortcut
- bx_options.Ouser_shortcut = new bx_param_string_c (BXP_USER_SHORTCUT,
- "Userbutton shortcut",
- "Defines the keyboard shortcut to be sent when you press the 'user' button in the headerbar.",
- "none", 16);
-
- // GDB stub
- bx_options.gdbstub.port = 1234;
- bx_options.gdbstub.text_base = 0;
- bx_options.gdbstub.data_base = 0;
- bx_options.gdbstub.bss_base = 0;
-
- bx_param_c *keyboard_init_list[] = {
- bx_options.Okeyboard_serial_delay,
- bx_options.Okeyboard_paste_delay,
- bx_options.keyboard.OuseMapping,
- bx_options.keyboard.Okeymap,
- bx_options.Okeyboard_type,
- bx_options.Ouser_shortcut,
- NULL
- };
- menu = new bx_list_c (BXP_MENU_KEYBOARD, "Configure Keyboard", "", keyboard_init_list);
- menu->get_options ()->set (menu->SHOW_PARENT);
-
- bx_param_c *other_init_list[] = {
- bx_options.Ofloppy_command_delay,
- bx_options.Oi440FXSupport,
- bx_options.cmos.OcmosImage,
- bx_options.cmos.Opath,
- SIM->get_param (BXP_CLOCK),
- SIM->get_param (BXP_LOAD32BITOS),
- NULL
- };
- menu = new bx_list_c (BXP_MENU_MISC, "Configure Everything Else", "", other_init_list);
- menu->get_options ()->set (menu->SHOW_PARENT);
-
-#if BX_WITH_WX
- bx_param_c *other_init_list2[] = {
-// bx_options.Osel_config,
-// bx_options.Osel_displaylib,
- bx_options.Ovga_update_interval,
- bx_options.log.Oprefix,
- bx_options.Omouse_enabled,
- bx_options.OfloppySigCheck,
- bx_options.Ofloppy_command_delay,
- bx_options.OnewHardDriveSupport,
- bx_options.Oprivate_colormap,
-#if BX_WITH_AMIGAOS
- bx_options.Ofullscreen,
- bx_options.Oscreenmode,
-#endif
- bx_options.Oi440FXSupport,
- bx_options.cmos.OcmosImage,
- bx_options.cmos.Opath,
- NULL
- };
- menu = new bx_list_c (BXP_MENU_MISC_2, "Other options", "", other_init_list2);
-#endif
-}
-
-void bx_reset_options ()
-{
- // drives
- bx_options.floppya.Opath->reset();
- bx_options.floppya.Odevtype->reset();
- bx_options.floppya.Otype->reset();
- bx_options.floppya.Ostatus->reset();
- bx_options.floppyb.Opath->reset();
- bx_options.floppyb.Odevtype->reset();
- bx_options.floppyb.Otype->reset();
- bx_options.floppyb.Ostatus->reset();
-
- for (Bit8u channel=0; channel<BX_MAX_ATA_CHANNEL; channel++) {
- bx_options.ata[channel].Opresent->reset();
- bx_options.ata[channel].Oioaddr1->reset();
- bx_options.ata[channel].Oioaddr2->reset();
- bx_options.ata[channel].Oirq->reset();
-
- for (Bit8u slave=0; slave<2; slave++) {
- bx_options.atadevice[channel][slave].Opresent->reset();
- bx_options.atadevice[channel][slave].Otype->reset();
- bx_options.atadevice[channel][slave].Omode->reset();
- bx_options.atadevice[channel][slave].Opath->reset();
- bx_options.atadevice[channel][slave].Ocylinders->reset();
- bx_options.atadevice[channel][slave].Oheads->reset();
- bx_options.atadevice[channel][slave].Ospt->reset();
- bx_options.atadevice[channel][slave].Ostatus->reset();
- bx_options.atadevice[channel][slave].Omodel->reset();
- bx_options.atadevice[channel][slave].Obiosdetect->reset();
- bx_options.atadevice[channel][slave].Otranslation->reset();
- }
- }
- bx_options.OnewHardDriveSupport->reset();
-
- // boot & memory
- bx_options.Obootdrive->reset();
- bx_options.OfloppySigCheck->reset();
- bx_options.memory.Osize->reset();
-
- // standard ports
- bx_options.com[0].Oenabled->reset();
- bx_options.com[0].Odev->reset();
- bx_options.par[0].Oenabled->reset();
- bx_options.par[0].Ooutfile->reset();
-
- // rom images
- bx_options.rom.Opath->reset();
- bx_options.rom.Oaddress->reset();
- bx_options.optrom[0].Opath->reset();
- bx_options.optrom[0].Oaddress->reset();
- bx_options.optrom[1].Opath->reset();
- bx_options.optrom[1].Oaddress->reset();
- bx_options.optrom[2].Opath->reset();
- bx_options.optrom[2].Oaddress->reset();
- bx_options.optrom[3].Opath->reset();
- bx_options.optrom[3].Oaddress->reset();
- bx_options.vgarom.Opath->reset();
-
- // interface
- bx_options.Ovga_update_interval->reset();
- bx_options.Omouse_enabled->reset();
- bx_options.Oips->reset();
- bx_options.Oprivate_colormap->reset();
-#if BX_WITH_AMIGAOS
- bx_options.Ofullscreen->reset();
- bx_options.Oscreenmode->reset();
-#endif
-
- // ne2k
- bx_options.ne2k.Opresent->reset();
- bx_options.ne2k.Oioaddr->reset();
- bx_options.ne2k.Oirq->reset();
- bx_options.ne2k.Omacaddr->reset();
- bx_options.ne2k.Oethmod->reset();
- bx_options.ne2k.Oethdev->reset();
- bx_options.ne2k.Oscript->reset();
-
- // SB16
- bx_options.sb16.Opresent->reset();
- bx_options.sb16.Omidifile->reset();
- bx_options.sb16.Owavefile->reset();
- bx_options.sb16.Ologfile->reset();
- bx_options.sb16.Omidimode->reset();
- bx_options.sb16.Owavemode->reset();
- bx_options.sb16.Ologlevel->reset();
- bx_options.sb16.Odmatimer->reset();
-
- // logfile
- bx_options.log.Ofilename->reset();
- bx_options.log.Oprefix->reset();
- bx_options.log.Odebugger_filename->reset();
-
- // loader
- bx_options.load32bitOSImage.OwhichOS->reset();
- bx_options.load32bitOSImage.Opath->reset();
- bx_options.load32bitOSImage.Oiolog->reset();
- bx_options.load32bitOSImage.Oinitrd->reset();
-
- // keyboard
- bx_options.Okeyboard_serial_delay->reset();
- bx_options.Okeyboard_paste_delay->reset();
- bx_options.keyboard.OuseMapping->reset();
- bx_options.keyboard.Okeymap->reset();
- bx_options.Okeyboard_type->reset();
- bx_options.Ouser_shortcut->reset();
-
- // Clock
- bx_options.clock.Otime0->reset();
- bx_options.clock.Osync->reset();
-
- // other
- bx_options.Ofloppy_command_delay->reset();
- bx_options.Oi440FXSupport->reset();
- bx_options.cmos.OcmosImage->reset();
- bx_options.cmos.Opath->reset();
- bx_options.Otext_snapshot_check->reset();
-}
-
-void bx_print_header ()
-{
- fprintf (stderr, "%s\n", divider);
- char buffer[128];
- sprintf (buffer, "Bochs x86 Emulator %s\n", VER_STRING);
- bx_center_print (stderr, buffer, 72);
- if (REL_STRING[0]) {
- sprintf (buffer, "%s\n", REL_STRING);
- bx_center_print (stderr, buffer, 72);
- }
- fprintf (stderr, "%s\n", divider);
-}
-
-#if BX_WITH_CARBON
-/* Original code by Darrell Walisser - dwaliss1@purdue.edu */
-
-static void setupWorkingDirectory (char *path)
-{
- char parentdir[MAXPATHLEN];
- char *c;
-
- strncpy ( parentdir, path, MAXPATHLEN );
- c = (char*) parentdir;
-
- while (*c != '\0') /* go to end */
- c++;
-
- while (*c != '/') /* back up to parent */
- c--;
-
- *c = '\0'; /* cut off last part (binary name) */
-
- /* chdir to the binary app's parent */
- int n;
- n = chdir (parentdir);
- if (n) BX_PANIC (("failed to change dir to parent"));
- /* chdir to the .app's parent */
- n = chdir ("../../../");
- if (n) BX_PANIC (("failed to change to ../../.."));
-}
-
-/* Panic button to display fatal errors.
- Completely self contained, can't rely on carbon.cc being available */
-static void carbonFatalDialog(const char *error, const char *exposition)
-{
- DialogRef alertDialog;
- CFStringRef cfError;
- CFStringRef cfExposition;
- DialogItemIndex index;
- AlertStdCFStringAlertParamRec alertParam = {0};
- fprintf(stderr, "Entering carbonFatalDialog: %s\n", error);
-
- // Init libraries
- InitCursor();
- // Assemble dialog
- cfError = CFStringCreateWithCString(NULL, error, kCFStringEncodingASCII);
- if(exposition != NULL)
- {
- cfExposition = CFStringCreateWithCString(NULL, exposition, kCFStringEncodingASCII);
- }
- else { cfExposition = NULL; }
- alertParam.version = kStdCFStringAlertVersionOne;
- alertParam.defaultText = CFSTR("Quit");
- alertParam.position = kWindowDefaultPosition;
- alertParam.defaultButton = kAlertStdAlertOKButton;
- // Display Dialog
- CreateStandardAlert(
- kAlertStopAlert,
- cfError,
- cfExposition, /* can be NULL */
- &alertParam, /* can be NULL */
- &alertDialog);
- RunStandardAlert( alertDialog, NULL, &index);
- // Cleanup
- CFRelease( cfError );
- if( cfExposition != NULL ) { CFRelease( cfExposition ); }
-}
-#endif
-
-int bxmain () {
-#ifdef HAVE_LOCALE_H
- // Initialize locale (for isprint() and other functions)
- setlocale (LC_ALL, "");
-#endif
- bx_user_quit = 0;
- bx_init_siminterface (); // create the SIM object
-
- static jmp_buf context;
- if (setjmp (context) == 0) {
- SIM->set_quit_context (&context);
- if (bx_init_main (bx_startup_flags.argc, bx_startup_flags.argv) < 0)
- return 0;
- // read a param to decide which config interface to start.
- // If one exists, start it. If not, just begin.
- bx_param_enum_c *ci_param = SIM->get_param_enum (BXP_SEL_CONFIG_INTERFACE);
- char *ci_name = ci_param->get_choice (ci_param->get ());
- if (!strcmp(ci_name, "textconfig")) {
- init_text_config_interface (); // in textconfig.h
- }
-#if BX_WITH_WX
- else if (!strcmp(ci_name, "wx")) {
- PLUG_load_plugin(wx, PLUGTYPE_CORE);
- }
-#endif
- else {
- BX_PANIC (("unsupported configuration interface '%s'", ci_name));
- }
- int status = SIM->configuration_interface (ci_name, CI_START);
- if (status == CI_ERR_NO_TEXT_CONSOLE)
- BX_PANIC (("Bochs needed the text console, but it was not usable"));
- // user quit the config interface, so just quit
- } else {
- // quit via longjmp
- }
-}
-
-// normal main function, presently in for all cases except for
-// wxWindows under win32.
-int main (int argc, char *argv[])
-{
- daemon(0, 0);
- bx_startup_flags.argc = argc;
- bx_startup_flags.argv = argv;
-#if BX_WITH_SDL && defined(WIN32)
- // if SDL/win32, try to create a console window.
- RedirectIOToConsole ();
-#endif
- return bxmain ();
-}
-
-void
-print_usage ()
-{
- fprintf(stderr,
- "Usage: bochs [flags] [bochsrc options]\n\n"
- " -n no configuration file\n"
- " -f configfile specify configuration file\n"
- " -q quick start (skip configuration interface)\n"
- " --help display this help and exit\n\n"
- "For information on Bochs configuration file arguments, see the\n"
-#if (!defined(WIN32)) && !BX_WITH_MACOS
- "bochsrc section in the user documentation or the man page of bochsrc.\n");
-#else
- "bochsrc section in the user documentation.\n");
-#endif
-}
-
-#ifdef BX_USE_VMX
-int domid = -1;
-unsigned long megabytes = 0;
-#endif
-int
-bx_init_main (int argc, char *argv[])
-{
- // To deal with initialization order problems inherent in C++, use the macros
- // SAFE_GET_IOFUNC and SAFE_GET_GENLOG to retrieve "io" and "genlog" in all
- // constructors or functions called by constructors. The macros test for
- // NULL and create the object if necessary, then return it. Ensure that io
- // and genlog get created, by making one reference to each macro right here.
- // All other code can reference io and genlog directly. Because these
- // objects are required for logging, and logging is so fundamental to
- // knowing what the program is doing, they are never free()d.
- SAFE_GET_IOFUNC(); // never freed
- SAFE_GET_GENLOG(); // never freed
-
- // initalization must be done early because some destructors expect
- // the bx_options to exist by the time they are called.
- bx_init_bx_dbg ();
- bx_init_options ();
-
- bx_print_header ();
-
-#ifdef BX_USE_VMX
- xc_handle = xc_interface_open();
- SIM->get_param_enum(BXP_BOCHS_START)->set (BX_QUICK_START);
-#else
- SIM->get_param_enum(BXP_BOCHS_START)->set (BX_RUN_START);
-#endif
-
- // interpret the args that start with -, like -q, -f, etc.
- int arg = 1, load_rcfile=1;
- while (arg < argc) {
- // parse next arg
- if (!strcmp ("--help", argv[arg]) || !strncmp ("-h", argv[arg], 2)) {
- print_usage();
- SIM->quit_sim (0);
- }
- else if (!strcmp ("-n", argv[arg])) {
- load_rcfile = 0;
- }
- else if (!strcmp ("-q", argv[arg])) {
- SIM->get_param_enum(BXP_BOCHS_START)->set (BX_QUICK_START);
- }
- else if (!strcmp ("-f", argv[arg])) {
- if (++arg >= argc) BX_PANIC(("-f must be followed by a filename"));
- else bochsrc_filename = argv[arg];
- }
- else if (!strcmp ("-qf", argv[arg])) {
- SIM->get_param_enum(BXP_BOCHS_START)->set (BX_QUICK_START);
- if (++arg >= argc) BX_PANIC(("-qf must be followed by a filename"));
- else bochsrc_filename = argv[arg];
- }
-#ifdef BX_USE_VMX
- else if (!strcmp ("-p", argv[arg])) {
- //get the polling port
- extern int ioreq_port;
- if (++arg >= argc) BX_PANIC(("-p must be followed by a polling port"));
- else sscanf(argv[arg], "%d", &ioreq_port);
- }
- else if (!strcmp ("-d", argv[arg])) {
- //get the domain id
- if (++arg >= argc) BX_PANIC(("-d must be followed by domainid"));
- else sscanf(argv[arg], "%d", &domid);
- }
- else if (!strcmp ("-m", argv[arg])) {
- //get the maxmem
- if (++arg >= argc)
- BX_PANIC(("-m must be followed by maxmem in megabytes"));
- else sscanf(argv[arg], "%d", &megabytes);
- }
-
-#endif
- else if (argv[arg][0] == '-') {
- print_usage();
- BX_PANIC (("command line arg '%s' was not understood", argv[arg]));
- }
- else {
- // the arg did not start with -, so stop interpreting flags
- break;
- }
- arg++;
- }
-
- int norcfile = 1;
-
- if (load_rcfile) {
- /* parse configuration file and command line arguments */
-#ifdef WIN32
- if (bochsrc_filename != NULL) {
- lstrcpy(bx_startup_flags.initial_dir, bochsrc_filename);
- } else {
- bx_startup_flags.initial_dir[0] = 0;
- }
-#endif
- if (bochsrc_filename == NULL) bochsrc_filename = bx_find_bochsrc ();
- if (bochsrc_filename)
- norcfile = bx_read_configuration (bochsrc_filename);
- }
-
- // parse the rest of the command line. This is done after reading the
- // configuration file so that the command line arguments can override
- // the settings from the file.
- if (bx_parse_cmdline (arg, argc, argv)) {
- BX_PANIC(("There were errors while parsing the command line"));
- return -1;
- }
- // initialize plugin system. This must happen before we attempt to
- // load any modules.
- plugin_startup();
- return 0;
-}
-
-bx_bool load_and_init_display_lib () {
- if (bx_gui != NULL) {
- // bx_gui has already been filled in. This happens when you start
- // the simulation for the second time.
- // Also, if you load wxWindows as the configuration interface. Its
- // plugin_init will install wxWindows as the bx_gui.
- return true;
- }
- BX_ASSERT (bx_gui == NULL);
- bx_param_enum_c *ci_param = SIM->get_param_enum (BXP_SEL_CONFIG_INTERFACE);
- char *ci_name = ci_param->get_choice (ci_param->get ());
- bx_param_enum_c *gui_param = SIM->get_param_enum(BXP_SEL_DISPLAY_LIBRARY);
- char *gui_name = gui_param->get_choice (gui_param->get ());
- if (!strcmp(ci_name, "wx")) {
- BX_ERROR(("change of the config interface to wx not implemented yet"));
- }
- if (!strcmp (gui_name, "wx")) {
- // they must not have used wx as the configuration interface, or bx_gui
- // would already be initialized. Sorry, it doesn't work that way.
- BX_ERROR (("wxWindows was not used as the configuration interface, so it cannot be used as the display library"));
- // choose another, hopefully different!
- gui_param->set (0);
- gui_name = gui_param->get_choice (gui_param->get ());
- if (!strcmp (gui_name, "wx")) {
- BX_PANIC (("no alternative display libraries are available"));
- return false;
- }
- BX_ERROR (("changing display library to '%s' instead", gui_name));
- }
-#if BX_WITH_NOGUI
- if (!strcmp (gui_name, "nogui"))
- PLUG_load_plugin (nogui, PLUGTYPE_OPTIONAL);
-#endif
-#if BX_WITH_RFB
- if (!strcmp (gui_name, "rfb"))
- PLUG_load_plugin (rfb, PLUGTYPE_OPTIONAL);
-#endif
-#if BX_WITH_X11
- if (!strcmp (gui_name, "x"))
- PLUG_load_plugin (x, PLUGTYPE_OPTIONAL);
-#endif
-#if BX_WITH_TERM
- if (!strcmp (gui_name, "term"))
- PLUG_load_plugin (term, PLUGTYPE_OPTIONAL);
-#endif
-
-#if BX_GUI_SIGHANDLER
- // set the flag for guis requiring a GUI sighandler.
- // useful when guis are compiled as plugins
- // only term for now
- if (!strcmp (gui_name, "term")) {
- bx_gui_sighandler = 1;
- }
-#endif
-
- BX_ASSERT (bx_gui != NULL);
- return true;
-}
-
-int
-bx_begin_simulation (int argc, char *argv[])
-{
- // deal with gui selection
- if (!load_and_init_display_lib ()) {
- BX_PANIC (("no gui module was loaded"));
- return 0;
- }
-#if BX_GDBSTUB
- // If using gdbstub, it will take control and call
- // bx_init_hardware() and cpu_loop()
- bx_gdbstub_init (argc, argv);
-#elif BX_DEBUGGER
- // If using the debugger, it will take control and call
- // bx_init_hardware() and cpu_loop()
- bx_dbg_main(argc, argv);
-#else
-
- bx_init_hardware();
-
- if (bx_options.load32bitOSImage.OwhichOS->get ()) {
- void bx_load32bitOSimagehack(void);
- bx_load32bitOSimagehack();
- }
-
- SIM->set_init_done (1);
-
- // update headerbar buttons since drive status can change during init
- bx_gui->update_drive_status_buttons ();
-
- // The set handler for mouse_enabled does not actually update the gui
- // until init_done is set. This forces the set handler to be called,
- // which sets up the mouse enabled GUI-specific stuff correctly.
- // Not a great solution but it works. BBD
- bx_options.Omouse_enabled->set (bx_options.Omouse_enabled->get ());
-
- if (BX_SMP_PROCESSORS == 1) {
- // only one processor, run as fast as possible by not messing with
- // quantums and loops.
- BX_CPU(0)->cpu_loop(1);
- // for one processor, the only reason for cpu_loop to return is
- // that kill_bochs_request was set by the GUI interface.
- } else {
- // SMP simulation: do a few instructions on each processor, then switch
- // to another. Increasing quantum speeds up overall performance, but
- // reduces granularity of synchronization between processors.
- int processor = 0;
- int quantum = 5;
- while (1) {
- // do some instructions in each processor
- BX_CPU(processor)->cpu_loop(quantum);
- processor = (processor+1) % BX_SMP_PROCESSORS;
- if (BX_CPU(0)->kill_bochs_request)
- break;
- if (processor == 0)
- BX_TICKN(quantum);
- }
- }
-#endif
- BX_INFO (("cpu loop quit, shutting down simulator"));
- bx_atexit ();
- return(0);
-}
-
-
-int
-bx_read_configuration (char *rcfile)
-{
- // parse rcfile first, then parse arguments in order.
- BX_INFO (("reading configuration from %s", rcfile));
- if (parse_bochsrc(rcfile) < 0) {
- BX_PANIC (("reading from %s failed", rcfile));
- return -1;
- }
- // update log actions
- for (int level=0; level<N_LOGLEV; level++) {
- int action = SIM->get_default_log_action (level);
- io->set_log_action (level, action);
- }
- return 0;
-}
-
-int bx_parse_cmdline (int arg, int argc, char *argv[])
-{
- //if (arg < argc) BX_INFO (("parsing command line arguments"));
-
- while (arg < argc) {
- BX_INFO (("parsing arg %d, %s", arg, argv[arg]));
- parse_line_unformatted("cmdline args", argv[arg]);
- arg++;
- }
- // update log actions
- for (int level=0; level<N_LOGLEV; level++) {
- int action = SIM->get_default_log_action (level);
- io->set_log_action (level, action);
- }
- return 0;
-}
-
- int
-bx_init_hardware()
-{
- // all configuration has been read, now initialize everything.
-
- if (SIM->get_param_enum(BXP_BOCHS_START)->get ()==BX_QUICK_START) {
- for (int level=0; level<N_LOGLEV; level++) {
- int action = SIM->get_default_log_action (level);
-#if !BX_USE_CONFIG_INTERFACE
- if (action == ACT_ASK) action = ACT_FATAL;
-#endif
- io->set_log_action (level, action);
- }
- }
-
- bx_pc_system.init_ips(bx_options.Oips->get ());
-
- if(bx_options.log.Ofilename->getptr()[0]!='-') {
- BX_INFO (("using log file %s", bx_options.log.Ofilename->getptr ()));
- io->init_log(bx_options.log.Ofilename->getptr ());
- }
-
- io->set_log_prefix(bx_options.log.Oprefix->getptr());
-
- // Output to the log file the cpu settings
- // This will by handy for bug reports
- BX_INFO(("Bochs x86 Emulator %s", VER_STRING));
- BX_INFO((" %s", REL_STRING));
- BX_INFO(("System configuration"));
- BX_INFO((" processors: %d",BX_SMP_PROCESSORS));
- BX_INFO((" A20 line support: %s",BX_SUPPORT_A20?"yes":"no"));
- BX_INFO((" APIC support: %s",BX_SUPPORT_APIC?"yes":"no"));
-
-#ifndef BX_USE_VMX
- BX_INFO(("CPU configuration"));
- BX_INFO((" level: %d",BX_CPU_LEVEL));
- BX_INFO((" fpu support: %s",BX_SUPPORT_FPU?"yes":"no"));
- BX_INFO((" paging support: %s, tlb enabled: %s",BX_SUPPORT_PAGING?"yes":"no",BX_USE_TLB?"yes":"no"));
- BX_INFO((" mmx support: %s",BX_SUPPORT_MMX?"yes":"no"));
- BX_INFO((" sse support: %s",BX_SUPPORT_SSE==2?"2":BX_SUPPORT_SSE==1?"1":"no"));
- BX_INFO((" v8086 mode support: %s",BX_SUPPORT_V8086_MODE?"yes":"no"));
- BX_INFO((" 3dnow! support: %s",BX_SUPPORT_3DNOW?"yes":"no"));
- BX_INFO((" PAE support: %s",BX_SupportPAE?"yes":"no"));
- BX_INFO((" PGE support: %s",BX_SupportGlobalPages?"yes":"no"));
- BX_INFO((" PSE support: %s",BX_SUPPORT_4MEG_PAGES?"yes":"no"));
- BX_INFO((" x86-64 support: %s",BX_SUPPORT_X86_64?"yes":"no"));
- BX_INFO((" SEP support: %s",BX_SUPPORT_SEP?"yes":"no"));
- BX_INFO(("Optimization configuration"));
- BX_INFO((" Guest2HostTLB support: %s",BX_SupportGuest2HostTLB?"yes":"no"));
- BX_INFO((" RepeatSpeedups support: %s",BX_SupportRepeatSpeedups?"yes":"no"));
- BX_INFO((" Icache support: %s",BX_SupportICache?"yes":"no"));
- BX_INFO((" Host Asm support: %s",BX_SupportHostAsms?"yes":"no"));
-#endif /* BX_USE_VMX */
-
- // set up memory and CPU objects
-#if BX_SUPPORT_APIC
- bx_generic_apic_c::reset_all_ids ();
-#endif
-
-#ifndef BX_USE_VMX
- // Check if there is a romimage
- if (strcmp(bx_options.rom.Opath->getptr (),"") == 0) {
- BX_ERROR(("No romimage to load. Is your bochsrc file loaded/valid ?"));
- }
-
-#if BX_SMP_PROCESSORS==1
- BX_MEM(0)->init_memory(bx_options.memory.Osize->get () * 1024*1024);
-
- // First load the optional ROM images
- if (strcmp(bx_options.optrom[0].Opath->getptr (),"") !=0 )
- BX_MEM(0)->load_ROM(bx_options.optrom[0].Opath->getptr (), bx_options.optrom[0].Oaddress->get (), 2);
- if (strcmp(bx_options.optrom[1].Opath->getptr (),"") !=0 )
- BX_MEM(0)->load_ROM(bx_options.optrom[1].Opath->getptr (), bx_options.optrom[1].Oaddress->get (), 2);
- if (strcmp(bx_options.optrom[2].Opath->getptr (),"") !=0 )
- BX_MEM(0)->load_ROM(bx_options.optrom[2].Opath->getptr (), bx_options.optrom[2].Oaddress->get (), 2);
- if (strcmp(bx_options.optrom[3].Opath->getptr (),"") !=0 )
- BX_MEM(0)->load_ROM(bx_options.optrom[3].Opath->getptr (), bx_options.optrom[3].Oaddress->get (), 2);
-
- // Then Load the BIOS and VGABIOS
- BX_MEM(0)->load_ROM(bx_options.rom.Opath->getptr (), bx_options.rom.Oaddress->get (), 0);
- BX_MEM(0)->load_ROM(bx_options.vgarom.Opath->getptr (), 0xc0000, 1);
-
- BX_CPU(0)->init (BX_MEM(0));
- BX_CPU(0)->set_cpu_id(0);
-#if BX_SUPPORT_APIC
- BX_CPU(0)->local_apic.set_id (0);
-#endif
- BX_INSTR_INIT(0);
- BX_CPU(0)->reset(BX_RESET_HARDWARE);
-#else
- // SMP initialization
- bx_mem_array[0] = new BX_MEM_C ();
- bx_mem_array[0]->init_memory(bx_options.memory.Osize->get () * 1024*1024);
-
- // First load the optional ROM images
- if (strcmp(bx_options.optrom[0].Opath->getptr (),"") !=0 )
- bx_mem_array[0]->load_ROM(bx_options.optrom[0].Opath->getptr (), bx_options.optrom[0].Oaddress->get (), 2);
- if (strcmp(bx_options.optrom[1].Opath->getptr (),"") !=0 )
- bx_mem_array[0]->load_ROM(bx_options.optrom[1].Opath->getptr (), bx_options.optrom[1].Oaddress->get (), 2);
- if (strcmp(bx_options.optrom[2].Opath->getptr (),"") !=0 )
- bx_mem_array[0]->load_ROM(bx_options.optrom[2].Opath->getptr (), bx_options.optrom[2].Oaddress->get (), 2);
- if (strcmp(bx_options.optrom[3].Opath->getptr (),"") !=0 )
- bx_mem_array[0]->load_ROM(bx_options.optrom[3].Opath->getptr (), bx_options.optrom[3].Oaddress->get (), 2);
-
- // Then Load the BIOS and VGABIOS
- bx_mem_array[0]->load_ROM(bx_options.rom.Opath->getptr (), bx_options.rom.Oaddress->get (), 0);
- bx_mem_array[0]->load_ROM(bx_options.vgarom.Opath->getptr (), 0xc0000, 1);
-
- for (int i=0; i<BX_SMP_PROCESSORS; i++) {
- BX_CPU(i) = new BX_CPU_C;
- BX_CPU(i)->init (bx_mem_array[0]);
- // assign apic ID from the index of this loop
- // if !BX_SUPPORT_APIC, this will not compile.
- BX_CPU(i)->set_cpu_id(i);
- BX_CPU(i)->local_apic.set_id (i);
- BX_INSTR_INIT(i);
- BX_CPU(i)->reset(BX_RESET_HARDWARE);
- }
-#endif
-#else
- // Assume UP for now for VMX
- bx_mem.init_memory(megabytes * 1024 * 1024);
- bx_cpu.init(&bx_mem);
-#endif // BX_USE_VMX
-
-#if BX_DEBUGGER == 0
- DEV_init_devices();
- DEV_reset_devices(BX_RESET_HARDWARE);
- bx_gui->init_signal_handlers ();
- bx_pc_system.start_timers();
-#endif
- BX_DEBUG(("bx_init_hardware is setting signal handlers"));
-// if not using debugger, then we can take control of SIGINT.
-#if !BX_DEBUGGER
- signal(SIGINT, bx_signal_handler);
-#endif
-
-#if BX_SHOW_IPS
-#ifndef __MINGW32__
- signal(SIGALRM, bx_signal_handler);
-#endif
- alarm( 1 );
-#endif
-
- return(0);
-}
-
-
-
- void
-bx_init_bx_dbg (void)
-{
- bx_dbg.floppy = 0;
- bx_dbg.keyboard = 0;
- bx_dbg.video = 0;
- bx_dbg.disk = 0;
- bx_dbg.pit = 0;
- bx_dbg.pic = 0;
- bx_dbg.bios = 0;
- bx_dbg.cmos = 0;
- bx_dbg.a20 = 0;
- bx_dbg.interrupts = 0;
- bx_dbg.exceptions = 0;
- bx_dbg.unsupported = 0;
- bx_dbg.temp = 0;
- bx_dbg.reset = 0;
- bx_dbg.mouse = 0;
- bx_dbg.io = 0;
- bx_dbg.debugger = 0;
- bx_dbg.xms = 0;
- bx_dbg.v8086 = 0;
- bx_dbg.paging = 0;
- bx_dbg.creg = 0;
- bx_dbg.dreg = 0;
- bx_dbg.dma = 0;
- bx_dbg.unsupported_io = 0;
- bx_dbg.record_io = 0;
- bx_dbg.serial = 0;
- bx_dbg.cdrom = 0;
-#ifdef MAGIC_BREAKPOINT
- bx_dbg.magic_break_enabled = 0;
-#endif
-
-}
-
-
-int
-bx_atexit(void)
-{
- static bx_bool been_here = 0;
- if (been_here) return 1; // protect from reentry
- been_here = 1;
-
- // in case we ended up in simulation mode, change back to config mode
- // so that the user can see any messages left behind on the console.
- SIM->set_display_mode (DISP_MODE_CONFIG);
-
-#if BX_PROVIDE_DEVICE_MODELS==1
- bx_pc_system.exit();
-#endif
-
-#if BX_DEBUGGER == 0
- if (SIM && SIM->get_init_done ()) {
- for (int cpu=0; cpu<BX_SMP_PROCESSORS; cpu++)
- if (BX_CPU(cpu)) BX_CPU(cpu)->atexit();
- }
-#endif
-
-#if BX_PCI_SUPPORT
- if (bx_options.Oi440FXSupport->get ()) {
- bx_devices.pluginPciBridge->print_i440fx_state();
- }
-#endif
-
- // restore signal handling to defaults
-#if !BX_DEBUGGER
- BX_INFO (("restoring default signal behavior"));
- signal(SIGINT, SIG_DFL);
-#endif
-
-#if BX_SHOW_IPS
-#ifndef __MINGW32__
- signal(SIGALRM, SIG_DFL);
-#endif
-#endif
- return 0;
-}
-
-#if BX_PROVIDE_MAIN
-
-char *
-bx_find_bochsrc ()
-{
- FILE *fd = NULL;
- char rcfile[512];
- Bit32u retry = 0, found = 0;
- // try several possibilities for the bochsrc before giving up
- while (!found) {
- rcfile[0] = 0;
- switch (retry++) {
- case 0: strcpy (rcfile, ".bochsrc"); break;
- case 1: strcpy (rcfile, "bochsrc"); break;
- case 2: strcpy (rcfile, "bochsrc.txt"); break;
-#ifdef WIN32
- case 3: strcpy (rcfile, "bochsrc.bxrc"); break;
-#elif !BX_WITH_MACOS
- // only try this on unix
- case 3:
- {
- char *ptr = getenv("HOME");
- if (ptr) snprintf (rcfile, sizeof(rcfile), "%s/.bochsrc", ptr);
- }
- break;
- case 4: strcpy (rcfile, "/etc/bochsrc"); break;
-#endif
- default:
- return NULL;
- }
- if (rcfile[0]) {
- BX_DEBUG (("looking for configuration in %s", rcfile));
- fd = fopen(rcfile, "r");
- if (fd) found = 1;
- }
- }
- assert (fd != NULL && rcfile[0] != 0);
- fclose (fd);
- return strdup (rcfile);
-}
-
- static int
-parse_bochsrc(char *rcfile)
-{
- FILE *fd = NULL;
- char *ret;
- char line[512];
-
- // try several possibilities for the bochsrc before giving up
-
- bochsrc_include_count++;
-
- fd = fopen (rcfile, "r");
- if (fd == NULL) return -1;
-
- int retval = 0;
- do {
- ret = fgets(line, sizeof(line)-1, fd);
- line[sizeof(line) - 1] = '\0';
- int len = strlen(line);
- if (len>0)
- line[len-1] = '\0';
- if ((ret != NULL) && strlen(line)) {
- if (parse_line_unformatted(rcfile, line) < 0) {
- retval = -1;
- break; // quit parsing after first error
- }
- }
- } while (!feof(fd));
- fclose(fd);
- bochsrc_include_count--;
- return retval;
-}
-
- static Bit32s
-parse_line_unformatted(char *context, char *line)
-{
-#define MAX_PARAMS_LEN 40
- char *ptr;
- unsigned i, string_i;
- char string[512];
- char *params[MAX_PARAMS_LEN];
- int num_params;
- bx_bool inquotes = 0;
- bx_bool comment = 0;
-
- memset(params, 0, sizeof(params));
- if (line == NULL) return 0;
-
- // if passed nothing but whitespace, just return
- for (i=0; i<strlen(line); i++) {
- if (!isspace(line[i])) break;
- }
- if (i>=strlen(line))
- return 0;
-
- num_params = 0;
-
- if (!strncmp(line, "#include", 8))
- ptr = strtok(line, " ");
- else
- ptr = strtok(line, ":");
- while ((ptr) && (!comment)) {
- string_i = 0;
- for (i=0; i<strlen(ptr); i++) {
- if (ptr[i] == '"')
- inquotes = !inquotes;
- else if ((ptr[i] == '#') && (strncmp(line+i, "#include", 8)) && !inquotes) {
- comment = 1;
- break;
- } else {
-#if BX_HAVE_GETENV
- // substitute environment variables.
- if (ptr[i] == '$') {
- char varname[512];
- char *pv = varname;
- char *value;
- *pv = 0;
- i++;
- while (isalpha(ptr[i]) || ptr[i]=='_') {
- *pv = ptr[i]; pv++; i++;
- }
- *pv = 0;
- if (strlen(varname)<1 || !(value = getenv(varname))) {
- BX_PANIC (("could not look up environment variable '%s'", varname));
- } else {
- // append value to the string
- for (pv=value; *pv; pv++)
- string[string_i++] = *pv;
- }
- }
-#endif
- if (!isspace(ptr[i]) || inquotes) {
- string[string_i++] = ptr[i];
- }
- }
- }
- string[string_i] = '\0';
- if (string_i == 0) break;
- if ( params[num_params] != NULL )
- {
- free(params[num_params]);
- params[num_params] = NULL;
- }
- if ( num_params < MAX_PARAMS_LEN )
- {
- params[num_params++] = strdup (string);
- ptr = strtok(NULL, ",");
- }
- else
- {
- BX_PANIC (("too many parameters, max is %d\n", MAX_PARAMS_LEN));
- }
- }
- Bit32s retval = parse_line_formatted(context, num_params, ¶ms[0]);
- for (i=0; i < MAX_PARAMS_LEN; i++)
- {
- if ( params[i] != NULL )
- {
- free(params[i]);
- params[i] = NULL;
- }
- }
- return retval;
-}
-
-// These macros are called for all parse errors, so that we can easily
-// change the behavior of all occurrences.
-#define PARSE_ERR(x) \
- do { BX_PANIC(x); return -1; } while (0)
-#define PARSE_WARN(x) \
- BX_ERROR(x)
-
- static Bit32s
-parse_line_formatted(char *context, int num_params, char *params[])
-{
- int i;
-
- if (num_params < 1) return 0;
- if (num_params < 2) {
- PARSE_ERR(("%s: a bochsrc option needs at least one parameter", context));
- }
-
- if (!strcmp(params[0], "#include")) {
- if (num_params != 2) {
- PARSE_ERR(("%s: ignoring malformed #include directive.", context));
- }
- if (!strcmp(params[1], context)) {
- PARSE_ERR(("%s: cannot include this file again.", context));
- }
- if (bochsrc_include_count == 2) {
- PARSE_ERR(("%s: include directive in an included file not supported yet.", context));
- }
- bx_read_configuration(params[1]);
- }
- else if (!strcmp(params[0], "floppya")) {
- for (i=1; i<num_params; i++) {
- if (!strncmp(params[i], "2_88=", 5)) {
- bx_options.floppya.Opath->set (¶ms[i][5]);
- bx_options.floppya.Otype->set (BX_FLOPPY_2_88);
- }
- else if (!strncmp(params[i], "1_44=", 5)) {
- bx_options.floppya.Opath->set (¶ms[i][5]);
- bx_options.floppya.Otype->set (BX_FLOPPY_1_44);
- }
- else if (!strncmp(params[i], "1_2=", 4)) {
- bx_options.floppya.Opath->set (¶ms[i][4]);
- bx_options.floppya.Otype->set (BX_FLOPPY_1_2);
- }
- else if (!strncmp(params[i], "720k=", 5)) {
- bx_options.floppya.Opath->set (¶ms[i][5]);
- bx_options.floppya.Otype->set (BX_FLOPPY_720K);
- }
- else if (!strncmp(params[i], "360k=", 5)) {
- bx_options.floppya.Opath->set (¶ms[i][5]);
- bx_options.floppya.Otype->set (BX_FLOPPY_360K);
- }
- // use CMOS reserved types?
- else if (!strncmp(params[i], "160k=", 5)) {
- bx_options.floppya.Opath->set (¶ms[i][5]);
- bx_options.floppya.Otype->set (BX_FLOPPY_160K);
- }
- else if (!strncmp(params[i], "180k=", 5)) {
- bx_options.floppya.Opath->set (¶ms[i][5]);
- bx_options.floppya.Otype->set (BX_FLOPPY_180K);
- }
- else if (!strncmp(params[i], "320k=", 5)) {
- bx_options.floppya.Opath->set (¶ms[i][5]);
- bx_options.floppya.Otype->set (BX_FLOPPY_320K);
- }
- else if (!strncmp(params[i], "status=ejected", 14)) {
- bx_options.floppya.Ostatus->set (BX_EJECTED);
- }
- else if (!strncmp(params[i], "status=inserted", 15)) {
- bx_options.floppya.Ostatus->set (BX_INSERTED);
- }
- else {
- PARSE_ERR(("%s: floppya attribute '%s' not understood.", context,
- params[i]));
- }
- }
- }
- else if (!strcmp(params[0], "gdbstub_port"))
- {
- if (num_params != 2)
- {
- fprintf(stderr, ".bochsrc: gdbstub_port directive: wrong # args.\n");
- exit(1);
- }
- bx_options.gdbstub.port = atoi(params[1]);
- }
- else if (!strcmp(params[0], "gdbstub_text_base"))
- {
- if (num_params != 2)
- {
- fprintf(stderr, ".bochsrc: gdbstub_text_base directive: wrong # args.\n");
- exit(1);
- }
- bx_options.gdbstub.text_base = atoi(params[1]);
- }
- else if (!strcmp(params[0], "gdbstub_data_base"))
- {
- if (num_params != 2)
- {
- fprintf(stderr, ".bochsrc: gdbstub_data_base directive: wrong # args.\n");
- exit(1);
- }
- bx_options.gdbstub.data_base = atoi(params[1]);
- }
- else if (!strcmp(params[0], "gdbstub_bss_base"))
- {
- if (num_params != 2)
- {
- fprintf(stderr, ".bochsrc: gdbstub_bss_base directive: wrong # args.\n");
- exit(1);
- }
- bx_options.gdbstub.bss_base = atoi(params[1]);
- }
-
- else if (!strcmp(params[0], "floppyb")) {
- for (i=1; i<num_params; i++) {
- if (!strncmp(params[i], "2_88=", 5)) {
- bx_options.floppyb.Opath->set (¶ms[i][5]);
- bx_options.floppyb.Otype->set (BX_FLOPPY_2_88);
- }
- else if (!strncmp(params[i], "1_44=", 5)) {
- bx_options.floppyb.Opath->set (¶ms[i][5]);
- bx_options.floppyb.Otype->set (BX_FLOPPY_1_44);
- }
- else if (!strncmp(params[i], "1_2=", 4)) {
- bx_options.floppyb.Opath->set (¶ms[i][4]);
- bx_options.floppyb.Otype->set (BX_FLOPPY_1_2);
- }
- else if (!strncmp(params[i], "720k=", 5)) {
- bx_options.floppyb.Opath->set (¶ms[i][5]);
- bx_options.floppyb.Otype->set (BX_FLOPPY_720K);
- }
- else if (!strncmp(params[i], "360k=", 5)) {
- bx_options.floppyb.Opath->set (¶ms[i][5]);
- bx_options.floppyb.Otype->set (BX_FLOPPY_360K);
- }
- // use CMOS reserved types?
- else if (!strncmp(params[i], "160k=", 5)) {
- bx_options.floppyb.Opath->set (¶ms[i][5]);
- bx_options.floppyb.Otype->set (BX_FLOPPY_160K);
- }
- else if (!strncmp(params[i], "180k=", 5)) {
- bx_options.floppyb.Opath->set (¶ms[i][5]);
- bx_options.floppyb.Otype->set (BX_FLOPPY_180K);
- }
- else if (!strncmp(params[i], "320k=", 5)) {
- bx_options.floppyb.Opath->set (¶ms[i][5]);
- bx_options.floppyb.Otype->set (BX_FLOPPY_320K);
- }
- else if (!strncmp(params[i], "status=ejected", 14)) {
- bx_options.floppyb.Ostatus->set (BX_EJECTED);
- }
- else if (!strncmp(params[i], "status=inserted", 15)) {
- bx_options.floppyb.Ostatus->set (BX_INSERTED);
- }
- else {
- PARSE_ERR(("%s: floppyb attribute '%s' not understood.", context,
- params[i]));
- }
- }
- }
-
- else if ((!strncmp(params[0], "ata", 3)) && (strlen(params[0]) == 4)) {
- Bit8u channel = params[0][3];
-
- if ((channel < '0') || (channel > '9')) {
- PARSE_ERR(("%s: ataX directive malformed.", context));
- }
- channel-='0';
- if (channel >= BX_MAX_ATA_CHANNEL) {
- PARSE_ERR(("%s: ataX directive malformed.", context));
- }
-
- if ((num_params < 2) || (num_params > 5)) {
- PARSE_ERR(("%s: ataX directive malformed.", context));
- }
-
- if (strncmp(params[1], "enabled=", 8)) {
- PARSE_ERR(("%s: ataX directive malformed.", context));
- }
- else {
- bx_options.ata[channel].Opresent->set (atol(¶ms[1][8]));
- }
-
- if (num_params > 2) {
- if (strncmp(params[2], "ioaddr1=", 8)) {
- PARSE_ERR(("%s: ataX directive malformed.", context));
- }
- else {
- if ( (params[2][8] == '0') && (params[2][9] == 'x') )
- bx_options.ata[channel].Oioaddr1->set (strtoul (¶ms[2][8], NULL, 16));
- else
- bx_options.ata[channel].Oioaddr1->set (strtoul (¶ms[2][8], NULL, 10));
- }
- }
-
- if (num_params > 3) {
- if (strncmp(params[3], "ioaddr2=", 8)) {
- PARSE_ERR(("%s: ataX directive malformed.", context));
- }
- else {
- if ( (params[3][8] == '0') && (params[3][9] == 'x') )
- bx_options.ata[channel].Oioaddr2->set (strtoul (¶ms[3][8], NULL, 16));
- else
- bx_options.ata[channel].Oioaddr2->set (strtoul (¶ms[3][8], NULL, 10));
- }
- }
-
- if (num_params > 4) {
- if (strncmp(params[4], "irq=", 4)) {
- PARSE_ERR(("%s: ataX directive malformed.", context));
- }
- else {
- bx_options.ata[channel].Oirq->set (atol(¶ms[4][4]));
- }
- }
- }
-
- // ataX-master, ataX-slave
- else if ((!strncmp(params[0], "ata", 3)) && (strlen(params[0]) > 4)) {
- Bit8u channel = params[0][3], slave = 0;
-
- if ((channel < '0') || (channel > '9')) {
- PARSE_ERR(("%s: ataX-master/slave directive malformed.", context));
- }
- channel-='0';
- if (channel >= BX_MAX_ATA_CHANNEL) {
- PARSE_ERR(("%s: ataX-master/slave directive malformed.", context));
- }
-
- if ((strcmp(¶ms[0][4], "-slave")) &&
- (strcmp(¶ms[0][4], "-master"))) {
- PARSE_ERR(("%s: ataX-master/slave directive malformed.", context));
- }
-
- if (!strcmp(¶ms[0][4], "-slave")) {
- slave = 1;
- }
-
- // This was originally meant to warn users about both diskc
- // and ata0-master defined, but it also prevent users to
- // override settings on the command line
- // (see [ 661010 ] cannot override ata-settings from cmdline)
- // if (bx_options.atadevice[channel][slave].Opresent->get()) {
- // BX_INFO(("%s: %s device of ata channel %d already defined.", context, slave?"slave":"master",channel));
- // }
-
- for (i=1; i<num_params; i++) {
- if (!strcmp(params[i], "type=disk")) {
- bx_options.atadevice[channel][slave].Otype->set (BX_ATA_DEVICE_DISK);
- }
- else if (!strcmp(params[i], "type=cdrom")) {
- bx_options.atadevice[channel][slave].Otype->set (BX_ATA_DEVICE_CDROM);
- }
- else if (!strcmp(params[i], "mode=flat")) {
- bx_options.atadevice[channel][slave].Omode->set (BX_ATA_MODE_FLAT);
- }
- else if (!strcmp(params[i], "mode=concat")) {
- bx_options.atadevice[channel][slave].Omode->set (BX_ATA_MODE_CONCAT);
- }
- else if (!strcmp(params[i], "mode=external")) {
- bx_options.atadevice[channel][slave].Omode->set (BX_ATA_MODE_EXTDISKSIM);
- }
- else if (!strcmp(params[i], "mode=dll")) {
- bx_options.atadevice[channel][slave].Omode->set (BX_ATA_MODE_DLL_HD);
- }
- else if (!strcmp(params[i], "mode=sparse")) {
- bx_options.atadevice[channel][slave].Omode->set (BX_ATA_MODE_SPARSE);
- }
- else if (!strcmp(params[i], "mode=vmware3")) {
- bx_options.atadevice[channel][slave].Omode->set (BX_ATA_MODE_VMWARE3);
- }
-// else if (!strcmp(params[i], "mode=split")) {
-// bx_options.atadevice[channel][slave].Omode->set (BX_ATA_MODE_SPLIT);
-// }
- else if (!strcmp(params[i], "mode=undoable")) {
- bx_options.atadevice[channel][slave].Omode->set (BX_ATA_MODE_UNDOABLE);
- }
- else if (!strcmp(params[i], "mode=growing")) {
- bx_options.atadevice[channel][slave].Omode->set (BX_ATA_MODE_GROWING);
- }
- else if (!strcmp(params[i], "mode=volatile")) {
- bx_options.atadevice[channel][slave].Omode->set (BX_ATA_MODE_VOLATILE);
- }
-// else if (!strcmp(params[i], "mode=z-undoable")) {
-// bx_options.atadevice[channel][slave].Omode->set (BX_ATA_MODE_Z_UNDOABLE);
-// }
-// else if (!strcmp(params[i], "mode=z-volatile")) {
-// bx_options.atadevice[channel][slave].Omode->set (BX_ATA_MODE_Z_VOLATILE);
-// }
- else if (!strncmp(params[i], "path=", 5)) {
- bx_options.atadevice[channel][slave].Opath->set (¶ms[i][5]);
- }
- else if (!strncmp(params[i], "cylinders=", 10)) {
- bx_options.atadevice[channel][slave].Ocylinders->set (atol(¶ms[i][10]));
- }
- else if (!strncmp(params[i], "heads=", 6)) {
- bx_options.atadevice[channel][slave].Oheads->set (atol(¶ms[i][6]));
- }
- else if (!strncmp(params[i], "spt=", 4)) {
- bx_options.atadevice[channel][slave].Ospt->set (atol(¶ms[i][4]));
- }
- else if (!strncmp(params[i], "model=", 6)) {
- bx_options.atadevice[channel][slave].Omodel->set(¶ms[i][6]);
- }
- else if (!strcmp(params[i], "biosdetect=none")) {
- bx_options.atadevice[channel][slave].Obiosdetect->set(BX_ATA_BIOSDETECT_NONE);
- }
- else if (!strcmp(params[i], "biosdetect=cmos")) {
- bx_options.atadevice[channel][slave].Obiosdetect->set(BX_ATA_BIOSDETECT_CMOS);
- }
- else if (!strcmp(params[i], "biosdetect=auto")) {
- bx_options.atadevice[channel][slave].Obiosdetect->set(BX_ATA_BIOSDETECT_AUTO);
- }
- else if (!strcmp(params[i], "translation=none")) {
- bx_options.atadevice[channel][slave].Otranslation->set(BX_ATA_TRANSLATION_NONE);
- }
- else if (!strcmp(params[i], "translation=lba")) {
- bx_options.atadevice[channel][slave].Otranslation->set(BX_ATA_TRANSLATION_LBA);
- }
- else if (!strcmp(params[i], "translation=large")) {
- bx_options.atadevice[channel][slave].Otranslation->set(BX_ATA_TRANSLATION_LARGE);
- }
- else if (!strcmp(params[i], "translation=echs")) { // synonym of large
- bx_options.atadevice[channel][slave].Otranslation->set(BX_ATA_TRANSLATION_LARGE);
- }
- else if (!strcmp(params[i], "translation=rechs")) {
- bx_options.atadevice[channel][slave].Otranslation->set(BX_ATA_TRANSLATION_RECHS);
- }
- else if (!strcmp(params[i], "translation=auto")) {
- bx_options.atadevice[channel][slave].Otranslation->set(BX_ATA_TRANSLATION_AUTO);
- }
- else if (!strcmp(params[i], "status=ejected")) {
- bx_options.atadevice[channel][slave].Ostatus->set(BX_EJECTED);
- }
- else if (!strcmp(params[i], "status=inserted")) {
- bx_options.atadevice[channel][slave].Ostatus->set(BX_INSERTED);
- }
- else if (!strncmp(params[i], "journal=", 8)) {
- bx_options.atadevice[channel][slave].Ojournal->set(¶ms[i][8]);
- }
- else {
- PARSE_ERR(("%s: ataX-master/slave directive malformed.", context));
- }
- }
-
- // Enables the ata device
- bx_options.atadevice[channel][slave].Opresent->set(1);
-
- // if enabled, check if device ok
- if (bx_options.atadevice[channel][slave].Opresent->get() == 1) {
- if (bx_options.atadevice[channel][slave].Otype->get() == BX_ATA_DEVICE_DISK) {
- if (strlen(bx_options.atadevice[channel][slave].Opath->getptr()) ==0)
- PARSE_WARN(("%s: ataX-master/slave has empty path", context));
- if ((bx_options.atadevice[channel][slave].Ocylinders->get() == 0) ||
- (bx_options.atadevice[channel][slave].Oheads->get() ==0 ) ||
- (bx_options.atadevice[channel][slave].Ospt->get() == 0)) {
- PARSE_WARN(("%s: ataX-master/slave cannot have zero cylinders, heads, or sectors/track", context));
- }
- }
- else if (bx_options.atadevice[channel][slave].Otype->get() == BX_ATA_DEVICE_CDROM) {
- if (strlen(bx_options.atadevice[channel][slave].Opath->getptr()) == 0) {
- PARSE_WARN(("%s: ataX-master/slave has empty path", context));
- }
- }
- else {
- PARSE_WARN(("%s: ataX-master/slave: type should be specified", context));
- }
- }
- }
-
- // Legacy disk options emulation
- else if (!strcmp(params[0], "diskc")) { // DEPRECATED
- BX_INFO(("WARNING: diskc directive is deprecated, use ata0-master: instead"));
- if (bx_options.atadevice[0][0].Opresent->get()) {
- PARSE_ERR(("%s: master device of ata channel 0 already defined.", context));
- }
- if (num_params != 5) {
- PARSE_ERR(("%s: diskc directive malformed.", context));
- }
- if (strncmp(params[1], "file=", 5) ||
- strncmp(params[2], "cyl=", 4) ||
- strncmp(params[3], "heads=", 6) ||
- strncmp(params[4], "spt=", 4)) {
- PARSE_ERR(("%s: diskc directive malformed.", context));
- }
- bx_options.ata[0].Opresent->set(1);
- bx_options.atadevice[0][0].Otype->set (BX_ATA_DEVICE_DISK);
- bx_options.atadevice[0][0].Opath->set (¶ms[1][5]);
- bx_options.atadevice[0][0].Ocylinders->set (atol(¶ms[2][4]));
- bx_options.atadevice[0][0].Oheads->set (atol(¶ms[3][6]));
- bx_options.atadevice[0][0].Ospt->set (atol(¶ms[4][4]));
- bx_options.atadevice[0][0].Opresent->set (1);
- }
- else if (!strcmp(params[0], "diskd")) { // DEPRECATED
- BX_INFO(("WARNING: diskd directive is deprecated, use ata0-slave: instead"));
- if (bx_options.atadevice[0][1].Opresent->get()) {
- PARSE_ERR(("%s: slave device of ata channel 0 already defined.", context));
- }
- if (num_params != 5) {
- PARSE_ERR(("%s: diskd directive malformed.", context));
- }
- if (strncmp(params[1], "file=", 5) ||
- strncmp(params[2], "cyl=", 4) ||
- strncmp(params[3], "heads=", 6) ||
- strncmp(params[4], "spt=", 4)) {
- PARSE_ERR(("%s: diskd directive malformed.", context));
- }
- bx_options.ata[0].Opresent->set(1);
- bx_options.atadevice[0][1].Otype->set (BX_ATA_DEVICE_DISK);
- bx_options.atadevice[0][1].Opath->set (¶ms[1][5]);
- bx_options.atadevice[0][1].Ocylinders->set (atol( ¶ms[2][4]));
- bx_options.atadevice[0][1].Oheads->set (atol( ¶ms[3][6]));
- bx_options.atadevice[0][1].Ospt->set (atol( ¶ms[4][4]));
- bx_options.atadevice[0][1].Opresent->set (1);
- }
- else if (!strcmp(params[0], "cdromd")) { // DEPRECATED
- BX_INFO(("WARNING: cdromd directive is deprecated, use ata0-slave: instead"));
- if (bx_options.atadevice[0][1].Opresent->get()) {
- PARSE_ERR(("%s: slave device of ata channel 0 already defined.", context));
- }
- if (num_params != 3) {
- PARSE_ERR(("%s: cdromd directive malformed.", context));
- }
- if (strncmp(params[1], "dev=", 4) || strncmp(params[2], "status=", 7)) {
- PARSE_ERR(("%s: cdromd directive malformed.", context));
- }
- bx_options.ata[0].Opresent->set(1);
- bx_options.atadevice[0][1].Otype->set (BX_ATA_DEVICE_CDROM);
- bx_options.atadevice[0][1].Opath->set (¶ms[1][4]);
- if (!strcmp(params[2], "status=inserted"))
- bx_options.atadevice[0][1].Ostatus->set (BX_INSERTED);
- else if (!strcmp(params[2], "status=ejected"))
- bx_options.atadevice[0][1].Ostatus->set (BX_EJECTED);
- else {
- PARSE_ERR(("%s: cdromd directive malformed.", context));
- }
- bx_options.atadevice[0][1].Opresent->set (1);
- }
-
- else if (!strcmp(params[0], "boot")) {
- if (!strcmp(params[1], "a")) {
- bx_options.Obootdrive->set (BX_BOOT_FLOPPYA);
- } else if (!strcmp(params[1], "floppy")) {
- bx_options.Obootdrive->set (BX_BOOT_FLOPPYA);
- } else if (!strcmp(params[1], "c")) {
- bx_options.Obootdrive->set (BX_BOOT_DISKC);
- } else if (!strcmp(params[1], "disk")) {
- bx_options.Obootdrive->set (BX_BOOT_DISKC);
- } else if (!strcmp(params[1], "cdrom")) {
- bx_options.Obootdrive->set (BX_BOOT_CDROM);
- } else {
- PARSE_ERR(("%s: boot directive with unknown boot device '%s'. use 'floppy', 'disk' or 'cdrom'.", context, params[1]));
- }
- }
-
- else if (!strcmp(params[0], "com1")) {
- for (i=1; i<num_params; i++) {
- if (!strncmp(params[i], "enabled=", 8)) {
- bx_options.com[0].Oenabled->set (atol(¶ms[i][8]));
- }
- else if (!strncmp(params[i], "dev=", 4)) {
- bx_options.com[0].Odev->set (¶ms[i][4]);
- bx_options.com[0].Oenabled->set (1);
- }
- else {
- PARSE_ERR(("%s: unknown parameter for com1 ignored.", context));
- }
- }
- }
-#if 0
- else if (!strcmp(params[0], "com2")) {
- for (i=1; i<num_params; i++) {
- if (!strncmp(params[i], "enabled=", 8)) {
- bx_options.com[1].Oenabled->set (atol(¶ms[i][8]));
- }
- else if (!strncmp(params[i], "dev=", 4)) {
- bx_options.com[1].Odev->set (¶ms[i][4]);
- bx_options.com[1].Oenabled->set (1);
- }
- else {
- PARSE_ERR(("%s: unknown parameter for com2 ignored.", context));
- }
- }
- }
- else if (!strcmp(params[0], "com3")) {
- for (i=1; i<num_params; i++) {
- if (!strncmp(params[i], "enabled=", 8)) {
- bx_options.com[2].Oenabled->set (atol(¶ms[i][8]));
- }
- else if (!strncmp(params[i], "dev=", 4)) {
- bx_options.com[2].Odev->set (¶ms[i][4]);
- bx_options.com[2].Oenabled->set (1);
- }
- else {
- PARSE_ERR(("%s: unknown parameter for com3 ignored.", context));
- }
- }
- }
- else if (!strcmp(params[0], "com4")) {
- for (i=1; i<num_params; i++) {
- if (!strncmp(params[i], "enabled=", 8)) {
- bx_options.com[3].Oenabled->set (atol(¶ms[i][8]));
- }
- else if (!strncmp(params[i], "dev=", 4)) {
- bx_options.com[3].Odev->set (¶ms[i][4]);
- bx_options.com[3].Oenabled->set (1);
- }
- else {
- PARSE_ERR(("%s: unknown parameter for com4 ignored.", context));
- }
- }
- }
-#endif
- else if (!strcmp(params[0], "usb1")) {
- for (i=1; i<num_params; i++) {
- if (!strncmp(params[i], "enabled=", 8)) {
- bx_options.usb[0].Oenabled->set (atol(¶ms[i][8]));
- }
- else if (!strncmp(params[i], "ioaddr=", 7)) {
- if ( (params[i][7] == '0') && (params[i][8] == 'x') )
- bx_options.usb[0].Oioaddr->set (strtoul (¶ms[i][7], NULL, 16));
- else
- bx_options.usb[0].Oioaddr->set (strtoul (¶ms[i][7], NULL, 10));
- bx_options.usb[0].Oenabled->set (1);
- }
- else if (!strncmp(params[i], "irq=", 4)) {
- bx_options.usb[0].Oirq->set (atol(¶ms[i][4]));
- }
- else {
- PARSE_ERR(("%s: unknown parameter for usb1 ignored.", context));
- }
- }
- }
- else if (!strcmp(params[0], "floppy_bootsig_check")) {
- if (num_params != 2) {
- PARSE_ERR(("%s: floppy_bootsig_check directive malformed.", context));
- }
- if (strncmp(params[1], "disabled=", 9)) {
- PARSE_ERR(("%s: floppy_bootsig_check directive malformed.", context));
- }
- if (params[1][9] == '0')
- bx_options.OfloppySigCheck->set (0);
- else if (params[1][9] == '1')
- bx_options.OfloppySigCheck->set (1);
- else {
- PARSE_ERR(("%s: floppy_bootsig_check directive malformed.", context));
- }
- }
- else if (!strcmp(params[0], "log")) {
- if (num_params != 2) {
- PARSE_ERR(("%s: log directive has wrong # args.", context));
- }
- bx_options.log.Ofilename->set (params[1]);
- }
- else if (!strcmp(params[0], "logprefix")) {
- if (num_params != 2) {
- PARSE_ERR(("%s: logprefix directive has wrong # args.", context));
- }
- bx_options.log.Oprefix->set (params[1]);
- }
- else if (!strcmp(params[0], "debugger_log")) {
- if (num_params != 2) {
- PARSE_ERR(("%s: debugger_log directive has wrong # args.", context));
- }
- bx_options.log.Odebugger_filename->set (params[1]);
- }
- else if (!strcmp(params[0], "panic")) {
- if (num_params != 2) {
- PARSE_ERR(("%s: panic directive malformed.", context));
- }
- if (strncmp(params[1], "action=", 7)) {
- PARSE_ERR(("%s: panic directive malformed.", context));
- }
- char *action = 7 + params[1];
- if (!strcmp(action, "fatal"))
- SIM->set_default_log_action (LOGLEV_PANIC, ACT_FATAL);
- else if (!strcmp (action, "report"))
- SIM->set_default_log_action (LOGLEV_PANIC, ACT_REPORT);
- else if (!strcmp (action, "ignore"))
- SIM->set_default_log_action (LOGLEV_PANIC, ACT_IGNORE);
- else if (!strcmp (action, "ask"))
- SIM->set_default_log_action (LOGLEV_PANIC, ACT_ASK);
- else {
- PARSE_ERR(("%s: panic directive malformed.", context));
- }
- }
- else if (!strcmp(params[0], "pass")) {
- if (num_params != 2) {
- PARSE_ERR(("%s: pass directive malformed.", context));
- }
- if (strncmp(params[1], "action=", 7)) {
- PARSE_ERR(("%s: pass directive malformed.", context));
- }
- char *action = 7 + params[1];
- if (!strcmp(action, "fatal"))
- SIM->set_default_log_action (LOGLEV_PASS, ACT_FATAL);
- else if (!strcmp (action, "report"))
- SIM->set_default_log_action (LOGLEV_PASS, ACT_REPORT);
- else if (!strcmp (action, "ignore"))
- SIM->set_default_log_action (LOGLEV_PASS, ACT_IGNORE);
- else if (!strcmp (action, "ask"))
- SIM->set_default_log_action (LOGLEV_PASS, ACT_ASK);
- else {
- PARSE_ERR(("%s: pass directive malformed.", context));
- }
- }
- else if (!strcmp(params[0], "error")) {
- if (num_params != 2) {
- PARSE_ERR(("%s: error directive malformed.", context));
- }
- if (strncmp(params[1], "action=", 7)) {
- PARSE_ERR(("%s: error directive malformed.", context));
- }
- char *action = 7 + params[1];
- if (!strcmp(action, "fatal"))
- SIM->set_default_log_action (LOGLEV_ERROR, ACT_FATAL);
- else if (!strcmp (action, "report"))
- SIM->set_default_log_action (LOGLEV_ERROR, ACT_REPORT);
- else if (!strcmp (action, "ignore"))
- SIM->set_default_log_action (LOGLEV_ERROR, ACT_IGNORE);
- else if (!strcmp (action, "ask"))
- SIM->set_default_log_action (LOGLEV_ERROR, ACT_ASK);
- else {
- PARSE_ERR(("%s: error directive malformed.", context));
- }
- }
- else if (!strcmp(params[0], "info")) {
- if (num_params != 2) {
- PARSE_ERR(("%s: info directive malformed.", context));
- }
- if (strncmp(params[1], "action=", 7)) {
- PARSE_ERR(("%s: info directive malformed.", context));
- }
- char *action = 7 + params[1];
- if (!strcmp(action, "fatal"))
- SIM->set_default_log_action (LOGLEV_INFO, ACT_FATAL);
- else if (!strcmp (action, "report"))
- SIM->set_default_log_action (LOGLEV_INFO, ACT_REPORT);
- else if (!strcmp (action, "ignore"))
- SIM->set_default_log_action (LOGLEV_INFO, ACT_IGNORE);
- else if (!strcmp (action, "ask"))
- SIM->set_default_log_action (LOGLEV_INFO, ACT_ASK);
- else {
- PARSE_ERR(("%s: info directive malformed.", context));
- }
- }
- else if (!strcmp(params[0], "debug")) {
- if (num_params != 2) {
- PARSE_ERR(("%s: debug directive malformed.", context));
- }
- if (strncmp(params[1], "action=", 7)) {
- PARSE_ERR(("%s: debug directive malformed.", context));
- }
- char *action = 7 + params[1];
- if (!strcmp(action, "fatal"))
- SIM->set_default_log_action (LOGLEV_DEBUG, ACT_FATAL);
- else if (!strcmp (action, "report"))
- SIM->set_default_log_action (LOGLEV_DEBUG, ACT_REPORT);
- else if (!strcmp (action, "ignore"))
- SIM->set_default_log_action (LOGLEV_DEBUG, ACT_IGNORE);
- else if (!strcmp (action, "ask"))
- SIM->set_default_log_action (LOGLEV_DEBUG, ACT_ASK);
- else {
- PARSE_ERR(("%s: debug directive malformed.", context));
- }
- }
- else if (!strcmp(params[0], "romimage")) {
- if (num_params != 3) {
- PARSE_ERR(("%s: romimage directive: wrong # args.", context));
- }
- if (strncmp(params[1], "file=", 5)) {
- PARSE_ERR(("%s: romimage directive malformed.", context));
- }
- if (strncmp(params[2], "address=", 8)) {
- PARSE_ERR(("%s: romimage directive malformed.", context));
- }
- bx_options.rom.Opath->set (¶ms[1][5]);
- if ( (params[2][8] == '0') && (params[2][9] == 'x') )
- bx_options.rom.Oaddress->set (strtoul (¶ms[2][8], NULL, 16));
- else
- bx_options.rom.Oaddress->set (strtoul (¶ms[2][8], NULL, 10));
- }
- else if (!strcmp(params[0], "optromimage1")) {
- if (num_params != 3) {
- PARSE_ERR(("%s: optromimage1 directive: wrong # args.", context));
- }
- if (strncmp(params[1], "file=", 5)) {
- PARSE_ERR(("%s: optromimage1 directive malformed.", context));
- }
- if (strncmp(params[2], "address=", 8)) {
- PARSE_ERR(("%s: optromimage2 directive malformed.", context));
- }
- bx_options.optrom[0].Opath->set (¶ms[1][5]);
- if ( (params[2][8] == '0') && (params[2][9] == 'x') )
- bx_options.optrom[0].Oaddress->set (strtoul (¶ms[2][8], NULL, 16));
- else
- bx_options.optrom[0].Oaddress->set (strtoul (¶ms[2][8], NULL, 10));
- }
- else if (!strcmp(params[0], "optromimage2")) {
- if (num_params != 3) {
- PARSE_ERR(("%s: optromimage2 directive: wrong # args.", context));
- }
- if (strncmp(params[1], "file=", 5)) {
- PARSE_ERR(("%s: optromimage2 directive malformed.", context));
- }
- if (strncmp(params[2], "address=", 8)) {
- PARSE_ERR(("%s: optromimage2 directive malformed.", context));
- }
- bx_options.optrom[1].Opath->set (¶ms[1][5]);
- if ( (params[2][8] == '0') && (params[2][9] == 'x') )
- bx_options.optrom[1].Oaddress->set (strtoul (¶ms[2][8], NULL, 16));
- else
- bx_options.optrom[1].Oaddress->set (strtoul (¶ms[2][8], NULL, 10));
- }
- else if (!strcmp(params[0], "optromimage3")) {
- if (num_params != 3) {
- PARSE_ERR(("%s: optromimage3 directive: wrong # args.", context));
- }
- if (strncmp(params[1], "file=", 5)) {
- PARSE_ERR(("%s: optromimage3 directive malformed.", context));
- }
- if (strncmp(params[2], "address=", 8)) {
- PARSE_ERR(("%s: optromimage2 directive malformed.", context));
- }
- bx_options.optrom[2].Opath->set (¶ms[1][5]);
- if ( (params[2][8] == '0') && (params[2][9] == 'x') )
- bx_options.optrom[2].Oaddress->set (strtoul (¶ms[2][8], NULL, 16));
- else
- bx_options.optrom[2].Oaddress->set (strtoul (¶ms[2][8], NULL, 10));
- }
- else if (!strcmp(params[0], "optromimage4")) {
- if (num_params != 3) {
- PARSE_ERR(("%s: optromimage4 directive: wrong # args.", context));
- }
- if (strncmp(params[1], "file=", 5)) {
- PARSE_ERR(("%s: optromimage4 directive malformed.", context));
- }
- if (strncmp(params[2], "address=", 8)) {
- PARSE_ERR(("%s: optromimage2 directive malformed.", context));
- }
- bx_options.optrom[3].Opath->set (¶ms[1][5]);
- if ( (params[2][8] == '0') && (params[2][9] == 'x') )
- bx_options.optrom[3].Oaddress->set (strtoul (¶ms[2][8], NULL, 16));
- else
- bx_options.optrom[3].Oaddress->set (strtoul (¶ms[2][8], NULL, 10));
- }
- else if (!strcmp(params[0], "vgaromimage")) {
- if (num_params != 2) {
- PARSE_ERR(("%s: vgaromimage directive: wrong # args.", context));
- }
- bx_options.vgarom.Opath->set (params[1]);
- }
- else if (!strcmp(params[0], "vga_update_interval")) {
- if (num_params != 2) {
- PARSE_ERR(("%s: vga_update_interval directive: wrong # args.", context));
- }
- bx_options.Ovga_update_interval->set (atol(params[1]));
- if (bx_options.Ovga_update_interval->get () < 50000) {
- BX_INFO(("%s: vga_update_interval seems awfully small!", context));
- }
- }
- else if (!strcmp(params[0], "keyboard_serial_delay")) {
- if (num_params != 2) {
- PARSE_ERR(("%s: keyboard_serial_delay directive: wrong # args.", context));
- }
- bx_options.Okeyboard_serial_delay->set (atol(params[1]));
- if (bx_options.Okeyboard_serial_delay->get () < 5) {
- PARSE_ERR (("%s: keyboard_serial_delay not big enough!", context));
- }
- }
- else if (!strcmp(params[0], "keyboard_paste_delay")) {
- if (num_params != 2) {
- PARSE_ERR(("%s: keyboard_paste_delay directive: wrong # args.", context));
- }
- bx_options.Okeyboard_paste_delay->set (atol(params[1]));
- if (bx_options.Okeyboard_paste_delay->get () < 1000) {
- PARSE_ERR (("%s: keyboard_paste_delay not big enough!", context));
- }
- }
- else if (!strcmp(params[0], "megs")) {
- if (num_params != 2) {
- PARSE_ERR(("%s: megs directive: wrong # args.", context));
- }
- bx_options.memory.Osize->set (atol(params[1]));
- }
- else if (!strcmp(params[0], "floppy_command_delay")) {
- if (num_params != 2) {
- PARSE_ERR(("%s: floppy_command_delay directive: wrong # args.", context));
- }
- bx_options.Ofloppy_command_delay->set (atol(params[1]));
- if (bx_options.Ofloppy_command_delay->get () < 100) {
- PARSE_ERR(("%s: floppy_command_delay not big enough!", context));
- }
- }
- else if (!strcmp(params[0], "ips")) {
- if (num_params != 2) {
- PARSE_ERR(("%s: ips directive: wrong # args.", context));
- }
- bx_options.Oips->set (atol(params[1]));
- if (bx_options.Oips->get () < BX_MIN_IPS) {
- BX_ERROR(("%s: WARNING: ips is AWFULLY low!", context));
- }
- }
- else if (!strcmp(params[0], "pit")) { // Deprecated
- if (num_params != 2) {
- PARSE_ERR(("%s: pit directive: wrong # args.", context));
- }
- BX_INFO(("WARNING: pit directive is deprecated, use clock: instead"));
- if (!strncmp(params[1], "realtime=", 9)) {
- switch (params[1][9]) {
- case '0':
- BX_INFO(("WARNING: not disabling realtime pit"));
- break;
- case '1': bx_options.clock.Osync->set (BX_CLOCK_SYNC_REALTIME); break;
- default: PARSE_ERR(("%s: pit expected realtime=[0|1] arg", context));
- }
- }
- else PARSE_ERR(("%s: pit expected realtime=[0|1] arg", context));
- }
- else if (!strcmp(params[0], "max_ips")) {
- if (num_params != 2) {
- PARSE_ERR(("%s: max_ips directive: wrong # args.", context));
- }
- BX_INFO(("WARNING: max_ips not implemented"));
- }
- else if (!strcmp(params[0], "text_snapshot_check")) {
- if (num_params != 2) {
- PARSE_ERR(("%s: text_snapshot_check directive: wrong # args.", context));
- }
- if (!strncmp(params[1], "enable", 6)) {
- bx_options.Otext_snapshot_check->set (1);
- }
- else if (!strncmp(params[1], "disable", 7)) {
- bx_options.Otext_snapshot_check->set (0);
- }
- else bx_options.Otext_snapshot_check->set (!!(atol(params[1])));
- }
- else if (!strcmp(params[0], "mouse")) {
- if (num_params != 2) {
- PARSE_ERR(("%s: mouse directive malformed.", context));
- }
- if (strncmp(params[1], "enabled=", 8)) {
- PARSE_ERR(("%s: mouse directive malformed.", context));
- }
- if (params[1][8] == '0' || params[1][8] == '1')
- bx_options.Omouse_enabled->set (params[1][8] - '0');
- else
- PARSE_ERR(("%s: mouse directive malformed.", context));
- }
- else if (!strcmp(params[0], "private_colormap")) {
- if (num_params != 2) {
- PARSE_ERR(("%s: private_colormap directive malformed.", context));
- }
- if (strncmp(params[1], "enabled=", 8)) {
- PARSE_ERR(("%s: private_colormap directive malformed.", context));
- }
- if (params[1][8] == '0' || params[1][8] == '1')
- bx_options.Oprivate_colormap->set (params[1][8] - '0');
- else {
- PARSE_ERR(("%s: private_colormap directive malformed.", context));
- }
- }
- else if (!strcmp(params[0], "fullscreen")) {
-#if BX_WITH_AMIGAOS
- if (num_params != 2) {
- PARSE_ERR(("%s: fullscreen directive malformed.", context));
- }
- if (strncmp(params[1], "enabled=", 8)) {
- PARSE_ERR(("%s: fullscreen directive malformed.", context));
- }
- if (params[1][8] == '0' || params[1][8] == '1') {
- bx_options.Ofullscreen->set (params[1][8] - '0');
- } else {
- PARSE_ERR(("%s: fullscreen directive malformed.", context));
- }
-#endif
- }
- else if (!strcmp(params[0], "screenmode")) {
-#if BX_WITH_AMIGAOS
- if (num_params != 2) {
- PARSE_ERR(("%s: screenmode directive malformed.", context));
- }
- if (strncmp(params[1], "name=", 5)) {
- PARSE_ERR(("%s: screenmode directive malformed.", context));
- }
- bx_options.Oscreenmode->set (strdup(¶ms[1][5]));
-#endif
- }
-
- else if (!strcmp(params[0], "sb16")) {
- for (i=1; i<num_params; i++) {
- if (!strncmp(params[i], "midi=", 5)) {
- bx_options.sb16.Omidifile->set (strdup(¶ms[i][5]));
- }
- else if (!strncmp(params[i], "midimode=", 9)) {
- bx_options.sb16.Omidimode->set (atol(¶ms[i][9]));
- }
- else if (!strncmp(params[i], "wave=", 5)) {
- bx_options.sb16.Owavefile->set (strdup(¶ms[i][5]));
- }
- else if (!strncmp(params[i], "wavemode=", 9)) {
- bx_options.sb16.Owavemode->set (atol(¶ms[i][9]));
- }
- else if (!strncmp(params[i], "log=", 4)) {
- bx_options.sb16.Ologfile->set (strdup(¶ms[i][4]));
- }
- else if (!strncmp(params[i], "loglevel=", 9)) {
- bx_options.sb16.Ologlevel->set (atol(¶ms[i][9]));
- }
- else if (!strncmp(params[i], "dmatimer=", 9)) {
- bx_options.sb16.Odmatimer->set (atol(¶ms[i][9]));
- }
- }
- if (bx_options.sb16.Odmatimer->get () > 0)
- bx_options.sb16.Opresent->set (1);
- }
-
- else if (!strcmp(params[0], "parport1")) {
- for (i=1; i<num_params; i++) {
- if (!strncmp(params[i], "enabled=", 8)) {
- bx_options.par[0].Oenabled->set (atol(¶ms[i][8]));
- }
- else if (!strncmp(params[i], "file=", 5)) {
- bx_options.par[0].Ooutfile->set (strdup(¶ms[i][5]));
- bx_options.par[0].Oenabled->set (1);
- }
- else {
- BX_ERROR(("%s: unknown parameter for parport1 ignored.", context));
- }
- }
- }
-
-#if 0
- else if (!strcmp(params[0], "parport2")) {
- for (i=1; i<num_params; i++) {
- if (!strncmp(params[i], "enabled=", 8)) {
- bx_options.par[1].Oenabled->set (atol(¶ms[i][8]));
- }
- else if (!strncmp(params[i], "file=", 5)) {
- bx_options.par[1].Ooutfile->set (strdup(¶ms[i][5]));
- bx_options.par[1].Oenabled->set (1);
- }
- else {
- BX_ERROR(("%s: unknown parameter for parport2 ignored.", context));
- }
- }
- }
-#endif
-
- else if (!strcmp(params[0], "i440fxsupport")) {
- if (num_params != 2) {
- PARSE_ERR(("%s: i440FXSupport directive malformed.", context));
- }
- if (strncmp(params[1], "enabled=", 8)) {
- PARSE_ERR(("%s: i440FXSupport directive malformed.", context));
- }
- if (params[1][8] == '0')
- bx_options.Oi440FXSupport->set (0);
- else if (params[1][8] == '1')
- bx_options.Oi440FXSupport->set (1);
- else {
- PARSE_ERR(("%s: i440FXSupport directive malformed.", context));
- }
- }
- else if (!strcmp(params[0], "newharddrivesupport")) {
- if (num_params != 2) {
- PARSE_ERR(("%s: newharddrivesupport directive malformed.", context));
- }
- if (strncmp(params[1], "enabled=", 8)) {
- PARSE_ERR(("%s: newharddrivesupport directive malformed.", context));
- }
- if (params[1][8] == '0')
- bx_options.OnewHardDriveSupport->set (0);
- else if (params[1][8] == '1')
- bx_options.OnewHardDriveSupport->set (1);
- else {
- PARSE_ERR(("%s: newharddrivesupport directive malformed.", context));
- }
- }
- else if (!strcmp(params[0], "cmosimage")) {
- if (num_params != 2) {
- PARSE_ERR(("%s: cmosimage directive: wrong # args.", context));
- }
- bx_options.cmos.Opath->set (strdup(params[1]));
- bx_options.cmos.OcmosImage->set (1); // CMOS Image is true
- }
- else if (!strcmp(params[0], "time0")) { // Deprectated
- BX_INFO(("WARNING: time0 directive is deprecated, use clock: instead"));
- if (num_params != 2) {
- PARSE_ERR(("%s: time0 directive: wrong # args.", context));
- }
- bx_options.clock.Otime0->set (atoi(params[1]));
- }
- else if (!strcmp(params[0], "clock")) {
- for (i=1; i<num_params; i++) {
- if (!strncmp(params[i], "sync=", 5)) {
- bx_options.clock.Osync->set_by_name (¶ms[i][5]);
- }
- else if (!strcmp(params[i], "time0=local")) {
- bx_options.clock.Otime0->set (BX_CLOCK_TIME0_LOCAL);
- }
- else if (!strcmp(params[i], "time0=utc")) {
- bx_options.clock.Otime0->set (BX_CLOCK_TIME0_UTC);
- }
- else if (!strncmp(params[i], "time0=", 6)) {
- bx_options.clock.Otime0->set (atoi(¶ms[i][6]));
- }
- else {
- BX_ERROR(("%s: unknown parameter for clock ignored.", context));
- }
- }
- }
-#ifdef MAGIC_BREAKPOINT
- else if (!strcmp(params[0], "magic_break")) {
- if (num_params != 2) {
- PARSE_ERR(("%s: magic_break directive: wrong # args.", context));
- }
- if (strncmp(params[1], "enabled=", 8)) {
- PARSE_ERR(("%s: magic_break directive malformed.", context));
- }
- if (params[1][8] == '0') {
- BX_INFO(("Ignoring magic break points"));
- bx_dbg.magic_break_enabled = 0;
- }
- else if (params[1][8] == '1') {
- BX_INFO(("Stopping on magic break points"));
- bx_dbg.magic_break_enabled = 1;
- }
- else {
- PARSE_ERR(("%s: magic_break directive malformed.", context));
- }
- }
-#endif
- else if (!strcmp(params[0], "ne2k")) {
- int tmp[6];
- char tmpchar[6];
- int valid = 0;
- int n;
- if (!bx_options.ne2k.Opresent->get ()) {
- bx_options.ne2k.Oethmod->set_by_name ("null");
- }
- for (i=1; i<num_params; i++) {
- if (!strncmp(params[i], "ioaddr=", 7)) {
- bx_options.ne2k.Oioaddr->set (strtoul(¶ms[i][7], NULL, 16));
- valid |= 0x01;
- }
- else if (!strncmp(params[i], "irq=", 4)) {
- bx_options.ne2k.Oirq->set (atol(¶ms[i][4]));
- valid |= 0x02;
- }
- else if (!strncmp(params[i], "mac=", 4)) {
- n = sscanf(¶ms[i][4], "%x:%x:%x:%x:%x:%x",
- &tmp[0],&tmp[1],&tmp[2],&tmp[3],&tmp[4],&tmp[5]);
- if (n != 6) {
- PARSE_ERR(("%s: ne2k mac address malformed.", context));
- }
- for (n=0;n<6;n++)
- tmpchar[n] = (unsigned char)tmp[n];
- bx_options.ne2k.Omacaddr->set (tmpchar);
- valid |= 0x04;
- }
- else if (!strncmp(params[i], "ethmod=", 7)) {
- if (!bx_options.ne2k.Oethmod->set_by_name (strdup(¶ms[i][7])))
- PARSE_ERR(("%s: ethernet module '%s' not available", context, strdup(¶ms[i][7])));
- }
- else if (!strncmp(params[i], "ethdev=", 7)) {
- bx_options.ne2k.Oethdev->set (strdup(¶ms[i][7]));
- }
- else if (!strncmp(params[i], "script=", 7)) {
- bx_options.ne2k.Oscript->set (strdup(¶ms[i][7]));
- }
- else {
- PARSE_ERR(("%s: ne2k directive malformed.", context));
- }
- }
- if (!bx_options.ne2k.Opresent->get ()) {
- if (valid == 0x07) {
- bx_options.ne2k.Opresent->set (1);
- }
- else {
- PARSE_ERR(("%s: ne2k directive incomplete (ioaddr, irq and mac are required)", context));
- }
- }
- }
-
- else if (!strcmp(params[0], "load32bitOSImage")) {
- if ( (num_params!=4) && (num_params!=5) ) {
- PARSE_ERR(("%s: load32bitOSImage directive: wrong # args.", context));
- }
- if (strncmp(params[1], "os=", 3)) {
- PARSE_ERR(("%s: load32bitOSImage: directive malformed.", context));
- }
- if (!strcmp(¶ms[1][3], "nullkernel")) {
- bx_options.load32bitOSImage.OwhichOS->set (Load32bitOSNullKernel);
- }
- else if (!strcmp(¶ms[1][3], "linux")) {
- bx_options.load32bitOSImage.OwhichOS->set (Load32bitOSLinux);
- }
- else {
- PARSE_ERR(("%s: load32bitOSImage: unsupported OS.", context));
- }
- if (strncmp(params[2], "path=", 5)) {
- PARSE_ERR(("%s: load32bitOSImage: directive malformed.", context));
- }
- if (strncmp(params[3], "iolog=", 6)) {
- PARSE_ERR(("%s: load32bitOSImage: directive malformed.", context));
- }
- bx_options.load32bitOSImage.Opath->set (strdup(¶ms[2][5]));
- bx_options.load32bitOSImage.Oiolog->set (strdup(¶ms[3][6]));
- if (num_params == 5) {
- if (strncmp(params[4], "initrd=", 7)) {
- PARSE_ERR(("%s: load32bitOSImage: directive malformed.", context));
- }
- bx_options.load32bitOSImage.Oinitrd->set (strdup(¶ms[4][7]));
- }
- }
- else if (!strcmp(params[0], "keyboard_type")) {
- if (num_params != 2) {
- PARSE_ERR(("%s: keyboard_type directive: wrong # args.", context));
- }
- if(strcmp(params[1],"xt")==0){
- bx_options.Okeyboard_type->set (BX_KBD_XT_TYPE);
- }
- else if(strcmp(params[1],"at")==0){
- bx_options.Okeyboard_type->set (BX_KBD_AT_TYPE);
- }
- else if(strcmp(params[1],"mf")==0){
- bx_options.Okeyboard_type->set (BX_KBD_MF_TYPE);
- }
- else{
- PARSE_ERR(("%s: keyboard_type directive: wrong arg %s.", context,params[1]));
- }
- }
-
- else if (!strcmp(params[0], "keyboard_mapping")
- ||!strcmp(params[0], "keyboardmapping")) {
- for (i=1; i<num_params; i++) {
- if (!strncmp(params[i], "enabled=", 8)) {
- bx_options.keyboard.OuseMapping->set (atol(¶ms[i][8]));
- }
- else if (!strncmp(params[i], "map=", 4)) {
- bx_options.keyboard.Okeymap->set (strdup(¶ms[i][4]));
- }
- }
- }
- else if (!strcmp(params[0], "user_shortcut")) {
- if (num_params != 2) {
- PARSE_ERR(("%s: user_shortcut directive: wrong # args.", context));
- }
- if(!strncmp(params[1], "keys=", 4)) {
- bx_options.Ouser_shortcut->set (strdup(¶ms[1][5]));
- }
- }
- else if (!strcmp(params[0], "config_interface")) {
- if (num_params != 2) {
- PARSE_ERR(("%s: config_interface directive: wrong # args.", context));
- }
- if (!bx_options.Osel_config->set_by_name (params[1]))
- PARSE_ERR(("%s: config_interface '%s' not available", context, params[1]));
- }
- else if (!strcmp(params[0], "display_library")) {
- if (num_params != 2) {
- PARSE_ERR(("%s: display_library directive: wrong # args.", context));
- }
- if (!bx_options.Osel_displaylib->set_by_name (params[1]))
- PARSE_ERR(("%s: display library '%s' not available", context, params[1]));
- }
- else {
- PARSE_ERR(( "%s: directive '%s' not understood", context, params[0]));
- }
- return 0;
-}
-
-static char *fdtypes[] = {
- "none", "1_2", "1_44", "2_88", "720k", "360k", "160k", "180k", "320k"
-};
-
-
-int
-bx_write_floppy_options (FILE *fp, int drive, bx_floppy_options *opt)
-{
- BX_ASSERT (drive==0 || drive==1);
- if (opt->Otype->get () == BX_FLOPPY_NONE) {
- fprintf (fp, "# no floppy%c\n", (char)'a'+drive);
- return 0;
- }
- BX_ASSERT (opt->Otype->get () > BX_FLOPPY_NONE && opt->Otype->get () <= BX_FLOPPY_LAST);
- fprintf (fp, "floppy%c: %s=\"%s\", status=%s\n",
- (char)'a'+drive,
- fdtypes[opt->Otype->get () - BX_FLOPPY_NONE],
- opt->Opath->getptr (),
- opt->Ostatus->get ()==BX_EJECTED ? "ejected" : "inserted");
- return 0;
-}
-
-int
-bx_write_ata_options (FILE *fp, Bit8u channel, bx_ata_options *opt)
-{
- fprintf (fp, "ata%d: enabled=%d", channel, opt->Opresent->get());
-
- if (opt->Opresent->get()) {
- fprintf (fp, ", ioaddr1=0x%x, ioaddr2=0x%x, irq=%d", opt->Oioaddr1->get(),
- opt->Oioaddr2->get(), opt->Oirq->get());
- }
-
- fprintf (fp, "\n");
- return 0;
-}
-
-int
-bx_write_atadevice_options (FILE *fp, Bit8u channel, Bit8u drive, bx_atadevice_options *opt)
-{
- if (opt->Opresent->get()) {
- fprintf (fp, "ata%d-%s: ", channel, drive==0?"master":"slave");
-
- if (opt->Otype->get() == BX_ATA_DEVICE_DISK) {
- fprintf (fp, "type=disk");
-
- switch(opt->Omode->get()) {
- case BX_ATA_MODE_FLAT:
- fprintf (fp, ", mode=flat");
- break;
- case BX_ATA_MODE_CONCAT:
- fprintf (fp, ", mode=concat");
- break;
- case BX_ATA_MODE_EXTDISKSIM:
- fprintf (fp, ", mode=external");
- break;
- case BX_ATA_MODE_DLL_HD:
- fprintf (fp, ", mode=dll");
- break;
- case BX_ATA_MODE_SPARSE:
- fprintf (fp, ", mode=sparse");
- break;
- case BX_ATA_MODE_VMWARE3:
- fprintf (fp, ", mode=vmware3");
- break;
-// case BX_ATA_MODE_SPLIT:
-// fprintf (fp, ", mode=split");
-// break;
- case BX_ATA_MODE_UNDOABLE:
- fprintf (fp, ", mode=undoable");
- break;
- case BX_ATA_MODE_GROWING:
- fprintf (fp, ", mode=growing");
- break;
- case BX_ATA_MODE_VOLATILE:
- fprintf (fp, ", mode=volatile");
- break;
-// case BX_ATA_MODE_Z_UNDOABLE:
-// fprintf (fp, ", mode=z-undoable");
-// break;
-// case BX_ATA_MODE_Z_VOLATILE:
-// fprintf (fp, ", mode=z-volatile");
-// break;
- }
-
- switch(opt->Otranslation->get()) {
- case BX_ATA_TRANSLATION_NONE:
- fprintf (fp, ", translation=none");
- break;
- case BX_ATA_TRANSLATION_LBA:
- fprintf (fp, ", translation=lba");
- break;
- case BX_ATA_TRANSLATION_LARGE:
- fprintf (fp, ", translation=large");
- break;
- case BX_ATA_TRANSLATION_RECHS:
- fprintf (fp, ", translation=rechs");
- break;
- case BX_ATA_TRANSLATION_AUTO:
- fprintf (fp, ", translation=auto");
- break;
- }
-
- fprintf (fp, ", path=\"%s\", cylinders=%d, heads=%d, spt=%d",
- opt->Opath->getptr(),
- opt->Ocylinders->get(), opt->Oheads->get(), opt->Ospt->get());
-
- if (opt->Ojournal->getptr() != NULL)
- if ( strcmp(opt->Ojournal->getptr(), "") != 0)
- fprintf (fp, ", journal=\"%s\"", opt->Ojournal->getptr());
-
- }
- else if (opt->Otype->get() == BX_ATA_DEVICE_CDROM) {
- fprintf (fp, "type=cdrom, path=\"%s\", status=%s",
- opt->Opath->getptr(),
- opt->Ostatus->get ()==BX_EJECTED ? "ejected" : "inserted");
- }
-
- switch(opt->Obiosdetect->get()) {
- case BX_ATA_BIOSDETECT_NONE:
- fprintf (fp, ", biosdetect=none");
- break;
- case BX_ATA_BIOSDETECT_CMOS:
- fprintf (fp, ", biosdetect=cmos");
- break;
- case BX_ATA_BIOSDETECT_AUTO:
- fprintf (fp, ", biosdetect=auto");
- break;
- }
- if (strlen(opt->Omodel->getptr())>0) {
- fprintf (fp, ", model=\"%s\"", opt->Omodel->getptr());
- }
-
- fprintf (fp, "\n");
- }
- return 0;
-}
-
-int
-bx_write_parport_options (FILE *fp, bx_parport_options *opt, int n)
-{
- fprintf (fp, "parport%d: enabled=%d", n, opt->Oenabled->get ());
- if (opt->Oenabled->get ()) {
- fprintf (fp, ", file=\"%s\"", opt->Ooutfile->getptr ());
- }
- fprintf (fp, "\n");
- return 0;
-}
-
-int
-bx_write_serial_options (FILE *fp, bx_serial_options *opt, int n)
-{
- fprintf (fp, "com%d: enabled=%d", n, opt->Oenabled->get ());
- if (opt->Oenabled->get ()) {
- fprintf (fp, ", dev=\"%s\"", opt->Odev->getptr ());
- }
- fprintf (fp, "\n");
- return 0;
-}
-
-int
-bx_write_usb_options (FILE *fp, bx_usb_options *opt, int n)
-{
- fprintf (fp, "usb%d: enabled=%d", n, opt->Oenabled->get ());
- if (opt->Oenabled->get ()) {
- fprintf (fp, ", ioaddr=0x%04x, irq=%d", opt->Oioaddr->get (),
- opt->Oirq->get ());
- }
- fprintf (fp, "\n");
- return 0;
-}
-
-int
-bx_write_sb16_options (FILE *fp, bx_sb16_options *opt)
-{
- if (!opt->Opresent->get ()) {
- fprintf (fp, "# no sb16\n");
- return 0;
- }
- fprintf (fp, "sb16: midimode=%d, midi=%s, wavemode=%d, wave=%s, loglevel=%d, log=%s, dmatimer=%d\n", opt->Omidimode->get (), opt->Omidifile->getptr (), opt->Owavemode->get (), opt->Owavefile->getptr (), opt->Ologlevel->get (), opt->Ologfile->getptr (), opt->Odmatimer->get ());
- return 0;
-}
-
-int
-bx_write_ne2k_options (FILE *fp, bx_ne2k_options *opt)
-{
- if (!opt->Opresent->get ()) {
- fprintf (fp, "# no ne2k\n");
- return 0;
- }
- char *ptr = opt->Omacaddr->getptr ();
- fprintf (fp, "ne2k: ioaddr=0x%x, irq=%d, mac=%02x:%02x:%02x:%02x:%02x:%02x, ethmod=%s, ethdev=%s, script=%s\n",
- opt->Oioaddr->get (),
- opt->Oirq->get (),
- (unsigned int)(0xff & ptr[0]),
- (unsigned int)(0xff & ptr[1]),
- (unsigned int)(0xff & ptr[2]),
- (unsigned int)(0xff & ptr[3]),
- (unsigned int)(0xff & ptr[4]),
- (unsigned int)(0xff & ptr[5]),
- opt->Oethmod->get_choice(opt->Oethmod->get()),
- opt->Oethdev->getptr (),
- opt->Oscript->getptr ());
- return 0;
-}
-
-int
-bx_write_loader_options (FILE *fp, bx_load32bitOSImage_t *opt)
-{
- if (opt->OwhichOS->get () == 0) {
- fprintf (fp, "# no loader\n");
- return 0;
- }
- BX_ASSERT(opt->OwhichOS->get () == Load32bitOSLinux || opt->OwhichOS->get () == Load32bitOSNullKernel);
- fprintf (fp, "load32bitOSImage: os=%s, path=%s, iolog=%s, initrd=%s\n",
- (opt->OwhichOS->get () == Load32bitOSLinux) ? "linux" : "nullkernel",
- opt->Opath->getptr (),
- opt->Oiolog->getptr (),
- opt->Oinitrd->getptr ());
- return 0;
-}
-
-int
-bx_write_clock_options (FILE *fp, bx_clock_options *opt)
-{
- fprintf (fp, "clock: ");
-
- switch (opt->Osync->get()) {
- case BX_CLOCK_SYNC_NONE:
- fprintf (fp, "sync=none");
- break;
- case BX_CLOCK_SYNC_REALTIME:
- fprintf (fp, "sync=realtime");
- break;
- case BX_CLOCK_SYNC_SLOWDOWN:
- fprintf (fp, "sync=slowdown");
- break;
- case BX_CLOCK_SYNC_BOTH:
- fprintf (fp, "sync=both");
- break;
- default:
- BX_PANIC(("Unknown value for sync method"));
- }
-
- switch (opt->Otime0->get()) {
- case 0: break;
- case BX_CLOCK_TIME0_LOCAL:
- fprintf (fp, ", time0=local");
- break;
- case BX_CLOCK_TIME0_UTC:
- fprintf (fp, ", time0=utc");
- break;
- default:
- fprintf (fp, ", time0=%u", opt->Otime0->get());
- }
-
- fprintf (fp, "\n");
- return 0;
-}
-
-int
-bx_write_log_options (FILE *fp, bx_log_options *opt)
-{
- fprintf (fp, "log: %s\n", opt->Ofilename->getptr ());
- fprintf (fp, "logprefix: %s\n", opt->Oprefix->getptr ());
- fprintf (fp, "debugger_log: %s\n", opt->Odebugger_filename->getptr ());
- fprintf (fp, "panic: action=%s\n",
- io->getaction(logfunctions::get_default_action (LOGLEV_PANIC)));
- fprintf (fp, "error: action=%s\n",
- io->getaction(logfunctions::get_default_action (LOGLEV_ERROR)));
- fprintf (fp, "info: action=%s\n",
- io->getaction(logfunctions::get_default_action (LOGLEV_INFO)));
- fprintf (fp, "debug: action=%s\n",
- io->getaction(logfunctions::get_default_action (LOGLEV_DEBUG)));
- fprintf (fp, "pass: action=%s\n",
- io->getaction(logfunctions::get_default_action (LOGLEV_PASS)));
- return 0;
-}
-
-int
-bx_write_keyboard_options (FILE *fp, bx_keyboard_options *opt)
-{
- fprintf (fp, "keyboard_mapping: enabled=%d, map=%s\n", opt->OuseMapping->get(), opt->Okeymap->getptr());
- return 0;
-}
-
-// return values:
-// 0: written ok
-// -1: failed
-// -2: already exists, and overwrite was off
-int
-bx_write_configuration (char *rc, int overwrite)
-{
- BX_INFO (("write configuration to %s\n", rc));
- // check if it exists. If so, only proceed if overwrite is set.
- FILE *fp = fopen (rc, "r");
- if (fp != NULL) {
- fclose (fp);
- if (!overwrite) return -2;
- }
- fp = fopen (rc, "w");
- if (fp == NULL) return -1;
- // finally it's open and we can start writing.
- fprintf (fp, "# configuration file generated by Bochs\n");
- fprintf (fp, "config_interface: %s\n", bx_options.Osel_config->get_choice(bx_options.Osel_config->get()));
- fprintf (fp, "display_library: %s\n", bx_options.Osel_displaylib->get_choice(bx_options.Osel_displaylib->get()));
- fprintf (fp, "megs: %d\n", bx_options.memory.Osize->get ());
- if (strlen (bx_options.rom.Opath->getptr ()) > 0)
- fprintf (fp, "romimage: file=%s, address=0x%05x\n", bx_options.rom.Opath->getptr(), (unsigned int)bx_options.rom.Oaddress->get ());
- else
- fprintf (fp, "# no romimage\n");
- if (strlen (bx_options.vgarom.Opath->getptr ()) > 0)
- fprintf (fp, "vgaromimage: %s\n", bx_options.vgarom.Opath->getptr ());
- else
- fprintf (fp, "# no vgaromimage\n");
- int bootdrive = bx_options.Obootdrive->get ();
- fprintf (fp, "boot: %s\n", (bootdrive==BX_BOOT_FLOPPYA) ? "floppy" : (bootdrive==BX_BOOT_DISKC) ? "disk" : "cdrom");
- // it would be nice to put this type of function as methods on
- // the structs like bx_floppy_options::print or something.
- bx_write_floppy_options (fp, 0, &bx_options.floppya);
- bx_write_floppy_options (fp, 1, &bx_options.floppyb);
- for (Bit8u channel=0; channel<BX_MAX_ATA_CHANNEL; channel++) {
- bx_write_ata_options (fp, channel, &bx_options.ata[channel]);
- bx_write_atadevice_options (fp, channel, 0, &bx_options.atadevice[channel][0]);
- bx_write_atadevice_options (fp, channel, 1, &bx_options.atadevice[channel][1]);
- }
- if (strlen (bx_options.optrom[0].Opath->getptr ()) > 0)
- fprintf (fp, "optromimage1: file=%s, address=0x%05x\n", bx_options.optrom[0].Opath->getptr(), (unsigned int)bx_options.optrom[0].Oaddress->get ());
- if (strlen (bx_options.optrom[1].Opath->getptr ()) > 0)
- fprintf (fp, "optromimage2: file=%s, address=0x%05x\n", bx_options.optrom[1].Opath->getptr(), (unsigned int)bx_options.optrom[1].Oaddress->get ());
- if (strlen (bx_options.optrom[2].Opath->getptr ()) > 0)
- fprintf (fp, "optromimage3: file=%s, address=0x%05x\n", bx_options.optrom[2].Opath->getptr(), (unsigned int)bx_options.optrom[2].Oaddress->get ());
- if (strlen (bx_options.optrom[3].Opath->getptr ()) > 0)
- fprintf (fp, "optromimage4: file=%s, address=0x%05x\n", bx_options.optrom[3].Opath->getptr(), (unsigned int)bx_options.optrom[3].Oaddress->get ());
- bx_write_parport_options (fp, &bx_options.par[0], 1);
- //bx_write_parport_options (fp, &bx_options.par[1], 2);
- bx_write_serial_options (fp, &bx_options.com[0], 1);
- //bx_write_serial_options (fp, &bx_options.com[1], 2);
- //bx_write_serial_options (fp, &bx_options.com[2], 3);
- //bx_write_serial_options (fp, &bx_options.com[3], 4);
- bx_write_usb_options (fp, &bx_options.usb[0], 1);
- bx_write_sb16_options (fp, &bx_options.sb16);
- fprintf (fp, "floppy_bootsig_check: disabled=%d\n", bx_options.OfloppySigCheck->get ());
- fprintf (fp, "vga_update_interval: %u\n", bx_options.Ovga_update_interval->get ());
- fprintf (fp, "keyboard_serial_delay: %u\n", bx_options.Okeyboard_serial_delay->get ());
- fprintf (fp, "keyboard_paste_delay: %u\n", bx_options.Okeyboard_paste_delay->get ());
- fprintf (fp, "floppy_command_delay: %u\n", bx_options.Ofloppy_command_delay->get ());
- fprintf (fp, "ips: %u\n", bx_options.Oips->get ());
- fprintf (fp, "text_snapshot_check: %d\n", bx_options.Otext_snapshot_check->get ());
- fprintf (fp, "mouse: enabled=%d\n", bx_options.Omouse_enabled->get ());
- fprintf (fp, "private_colormap: enabled=%d\n", bx_options.Oprivate_colormap->get ());
-#if BX_WITH_AMIGAOS
- fprintf (fp, "fullscreen: enabled=%d\n", bx_options.Ofullscreen->get ());
- fprintf (fp, "screenmode: name=\"%s\"\n", bx_options.Oscreenmode->getptr ());
-#endif
- fprintf (fp, "i440fxsupport: enabled=%d\n", bx_options.Oi440FXSupport->get ());
- bx_write_clock_options (fp, &bx_options.clock);
- bx_write_ne2k_options (fp, &bx_options.ne2k);
- fprintf (fp, "newharddrivesupport: enabled=%d\n", bx_options.OnewHardDriveSupport->get ());
- bx_write_loader_options (fp, &bx_options.load32bitOSImage);
- bx_write_log_options (fp, &bx_options.log);
- bx_write_keyboard_options (fp, &bx_options.keyboard);
- fprintf (fp, "keyboard_type: %s\n", bx_options.Okeyboard_type->get ()==BX_KBD_XT_TYPE?"xt":
- bx_options.Okeyboard_type->get ()==BX_KBD_AT_TYPE?"at":"mf");
- fprintf (fp, "user_shortcut: keys=%s\n", bx_options.Ouser_shortcut->getptr ());
- if (strlen (bx_options.cmos.Opath->getptr ()) > 0)
- fprintf (fp, "cmosimage: %s\n", bx_options.cmos.Opath->getptr());
- else
- fprintf (fp, "# no cmosimage\n");
- fclose (fp);
- return 0;
-}
-#endif // #if BX_PROVIDE_MAIN
-
- void
-bx_signal_handler( int signum)
-{
- // in a multithreaded environment, a signal such as SIGINT can be sent to all
- // threads. This function is only intended to handle signals in the
- // simulator thread. It will simply return if called from any other thread.
- // Otherwise the BX_PANIC() below can be called in multiple threads at
- // once, leading to multiple threads trying to display a dialog box,
- // leading to GUI deadlock.
- if (!SIM->is_sim_thread ()) {
- BX_INFO (("bx_signal_handler: ignored sig %d because it wasn't called from the simulator thread", signum));
- return;
- }
-#if BX_GUI_SIGHANDLER
- if (bx_gui_sighandler) {
- // GUI signal handler gets first priority, if the mask says it's wanted
- if ((1<<signum) & bx_gui->get_sighandler_mask ()) {
- bx_gui->sighandler (signum);
- return;
- }
- }
-#endif
-
-#if BX_SHOW_IPS
- extern unsigned long ips_count;
-
- if (signum == SIGALRM ) {
- BX_INFO(("ips = %lu", ips_count));
- ips_count = 0;
-#ifndef __MINGW32__
- signal(SIGALRM, bx_signal_handler);
- alarm( 1 );
-#endif
- return;
- }
-#endif
-
-#if BX_GUI_SIGHANDLER
- if (bx_gui_sighandler) {
- if ((1<<signum) & bx_gui->get_sighandler_mask ()) {
- bx_gui->sighandler (signum);
- return;
- }
- }
-#endif
- BX_PANIC(("SIGNAL %u caught", signum));
-}
-
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: ne2k.cc,v 1.56.2.1 2004/02/02 22:37:22 cbothamy Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-// Peter Grehan (grehan@iprg.nokia.com) coded all of this
-// NE2000/ether stuff.
-
-// Define BX_PLUGGABLE in files that can be compiled into plugins. For
-// platforms that require a special tag on exported symbols, BX_PLUGGABLE
-// is used to know when we are exporting symbols and when we are importing.
-#define BX_PLUGGABLE
-
-#include "bochs.h"
-#if BX_NE2K_SUPPORT
-
-//Never completely fill the ne2k ring so that we never
-// hit the unclear completely full buffer condition.
-#define BX_NE2K_NEVER_FULL_RING (1)
-
-#define LOG_THIS theNE2kDevice->
-
-bx_ne2k_c *theNE2kDevice = NULL;
-
- int
-libne2k_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[])
-{
- theNE2kDevice = new bx_ne2k_c ();
- bx_devices.pluginNE2kDevice = theNE2kDevice;
- BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theNE2kDevice, BX_PLUGIN_NE2K);
- return(0); // Success
-}
-
- void
-libne2k_LTX_plugin_fini(void)
-{
-}
-
-bx_ne2k_c::bx_ne2k_c(void)
-{
- put("NE2K");
- settype(NE2KLOG);
- s.tx_timer_index = BX_NULL_TIMER_HANDLE;
-}
-
-
-bx_ne2k_c::~bx_ne2k_c(void)
-{
- // nothing for now
-}
-
-//
-// reset - restore state to power-up, cancelling all i/o
-//
-void
-bx_ne2k_c::reset(unsigned type)
-{
- BX_DEBUG (("reset"));
- // Zero out registers and memory
- memset( & BX_NE2K_THIS s.CR, 0, sizeof(BX_NE2K_THIS s.CR) );
- memset( & BX_NE2K_THIS s.ISR, 0, sizeof(BX_NE2K_THIS s.ISR));
- memset( & BX_NE2K_THIS s.IMR, 0, sizeof(BX_NE2K_THIS s.IMR));
- memset( & BX_NE2K_THIS s.DCR, 0, sizeof(BX_NE2K_THIS s.DCR));
- memset( & BX_NE2K_THIS s.TCR, 0, sizeof(BX_NE2K_THIS s.TCR));
- memset( & BX_NE2K_THIS s.TSR, 0, sizeof(BX_NE2K_THIS s.TSR));
- memset( & BX_NE2K_THIS s.RCR, 0, sizeof(BX_NE2K_THIS s.RCR));
- memset( & BX_NE2K_THIS s.RSR, 0, sizeof(BX_NE2K_THIS s.RSR));
- BX_NE2K_THIS s.local_dma = 0;
- BX_NE2K_THIS s.page_start = 0;
- BX_NE2K_THIS s.page_stop = 0;
- BX_NE2K_THIS s.bound_ptr = 0;
- BX_NE2K_THIS s.tx_page_start = 0;
- BX_NE2K_THIS s.num_coll = 0;
- BX_NE2K_THIS s.tx_bytes = 0;
- BX_NE2K_THIS s.fifo = 0;
- BX_NE2K_THIS s.remote_dma = 0;
- BX_NE2K_THIS s.remote_start = 0;
- BX_NE2K_THIS s.remote_bytes = 0;
- BX_NE2K_THIS s.tallycnt_0 = 0;
- BX_NE2K_THIS s.tallycnt_1 = 0;
- BX_NE2K_THIS s.tallycnt_2 = 0;
-
- memset( & BX_NE2K_THIS s.physaddr, 0, sizeof(BX_NE2K_THIS s.physaddr));
- memset( & BX_NE2K_THIS s.mchash, 0, sizeof(BX_NE2K_THIS s.mchash));
- BX_NE2K_THIS s.curr_page = 0;
-
- BX_NE2K_THIS s.rempkt_ptr = 0;
- BX_NE2K_THIS s.localpkt_ptr = 0;
- BX_NE2K_THIS s.address_cnt = 0;
-
- memset( & BX_NE2K_THIS s.mem, 0, sizeof(BX_NE2K_THIS s.mem));
-
- // Set power-up conditions
- BX_NE2K_THIS s.CR.stop = 1;
- BX_NE2K_THIS s.CR.rdma_cmd = 4;
- BX_NE2K_THIS s.ISR.reset = 1;
- BX_NE2K_THIS s.DCR.longaddr = 1;
- DEV_pic_lower_irq(BX_NE2K_THIS s.base_irq);
-}
-
-//
-// read_cr/write_cr - utility routines for handling reads/writes to
-// the Command Register
-//
-Bit32u
-bx_ne2k_c::read_cr(void)
-{
- Bit32u val =
- (((BX_NE2K_THIS s.CR.pgsel & 0x03) << 6) |
- ((BX_NE2K_THIS s.CR.rdma_cmd & 0x07) << 3) |
- (BX_NE2K_THIS s.CR.tx_packet << 2) |
- (BX_NE2K_THIS s.CR.start << 1) |
- (BX_NE2K_THIS s.CR.stop));
- BX_DEBUG(("read CR returns 0x%08x", val));
- return val;
-}
-
-void
-bx_ne2k_c::write_cr(Bit32u value)
-{
- BX_DEBUG(("wrote 0x%02x to CR", value));
-
- // Validate remote-DMA
- if ((value & 0x38) == 0x00) {
- BX_DEBUG(("CR write - invalid rDMA value 0"));
- value |= 0x20; /* dma_cmd == 4 is a safe default */
- }
-
- // Check for s/w reset
- if (value & 0x01) {
- BX_NE2K_THIS s.ISR.reset = 1;
- BX_NE2K_THIS s.CR.stop = 1;
- } else {
- BX_NE2K_THIS s.CR.stop = 0;
- }
-
- BX_NE2K_THIS s.CR.rdma_cmd = (value & 0x38) >> 3;
-
- // If start command issued, the RST bit in the ISR
- // must be cleared
- if ((value & 0x02) && !BX_NE2K_THIS s.CR.start) {
- BX_NE2K_THIS s.ISR.reset = 0;
- }
-
- BX_NE2K_THIS s.CR.start = ((value & 0x02) == 0x02);
- BX_NE2K_THIS s.CR.pgsel = (value & 0xc0) >> 6;
-
- // Check for send-packet command
- if (BX_NE2K_THIS s.CR.rdma_cmd == 3) {
- // Set up DMA read from receive ring
- BX_NE2K_THIS s.remote_start = BX_NE2K_THIS s.remote_dma = BX_NE2K_THIS s.bound_ptr * 256;
- BX_NE2K_THIS s.remote_bytes = *((Bit16u*) & BX_NE2K_THIS s.mem[BX_NE2K_THIS s.bound_ptr * 256 + 2 - BX_NE2K_MEMSTART]);
- BX_INFO(("Sending buffer #x%x length %d",
- BX_NE2K_THIS s.remote_start,
- BX_NE2K_THIS s.remote_bytes));
- }
-
- // Check for start-tx
- if ((value & 0x04) && BX_NE2K_THIS s.TCR.loop_cntl) {
- if (BX_NE2K_THIS s.TCR.loop_cntl != 1) {
- BX_INFO(("Loop mode %d not supported.", BX_NE2K_THIS s.TCR.loop_cntl));
- } else {
- rx_frame (& BX_NE2K_THIS s.mem[BX_NE2K_THIS s.tx_page_start*256 - BX_NE2K_MEMSTART],
- BX_NE2K_THIS s.tx_bytes);
- }
- } else if (value & 0x04) {
- if (BX_NE2K_THIS s.CR.stop || !BX_NE2K_THIS s.CR.start)
- BX_PANIC(("CR write - tx start, dev in reset"));
-
- if (BX_NE2K_THIS s.tx_bytes == 0)
- BX_PANIC(("CR write - tx start, tx bytes == 0"));
-
-#ifdef notdef
- // XXX debug stuff
- printf("packet tx (%d bytes):\t", BX_NE2K_THIS s.tx_bytes);
- for (int i = 0; i < BX_NE2K_THIS s.tx_bytes; i++) {
- printf("%02x ", BX_NE2K_THIS s.mem[BX_NE2K_THIS s.tx_page_start*256 -
- BX_NE2K_MEMSTART + i]);
- if (i && (((i+1) % 16) == 0))
- printf("\t");
- }
- printf("");
-#endif
-
- // Send the packet to the system driver
- BX_NE2K_THIS ethdev->sendpkt(& BX_NE2K_THIS s.mem[BX_NE2K_THIS s.tx_page_start*256 - BX_NE2K_MEMSTART], BX_NE2K_THIS s.tx_bytes);
-
- // some more debug
- if (BX_NE2K_THIS s.tx_timer_active)
- BX_PANIC(("CR write, tx timer still active"));
-
- // Schedule a timer to trigger a tx-complete interrupt
- // The number of microseconds is the bit-time / 10.
- // The bit-time is the preamble+sfd (64 bits), the
- // inter-frame gap (96 bits), the CRC (4 bytes), and the
- // the number of bits in the frame (s.tx_bytes * 8).
- //
- bx_pc_system.activate_timer(BX_NE2K_THIS s.tx_timer_index,
- (64 + 96 + 4*8 + BX_NE2K_THIS s.tx_bytes*8)/10,
- 0); // not continuous
- }
-
- // Linux probes for an interrupt by setting up a remote-DMA read
- // of 0 bytes with remote-DMA completion interrupts enabled.
- // Detect this here
- if (BX_NE2K_THIS s.CR.rdma_cmd == 0x01 &&
- BX_NE2K_THIS s.CR.start &&
- BX_NE2K_THIS s.remote_bytes == 0) {
- BX_NE2K_THIS s.ISR.rdma_done = 1;
- if (BX_NE2K_THIS s.IMR.rdma_inte) {
- DEV_pic_raise_irq(BX_NE2K_THIS s.base_irq);
- }
- }
-}
-
-//
-// chipmem_read/chipmem_write - access the 64K private RAM.
-// The ne2000 memory is accessed through the data port of
-// the asic (offset 0) after setting up a remote-DMA transfer.
-// Both byte and word accesses are allowed.
-// The first 16 bytes contains the MAC address at even locations,
-// and there is 16K of buffer memory starting at 16K
-//
-Bit32u BX_CPP_AttrRegparmN(2)
-bx_ne2k_c::chipmem_read(Bit32u address, unsigned int io_len)
-{
- Bit32u retval = 0;
-
- if ((io_len == 2) && (address & 0x1))
- BX_PANIC(("unaligned chipmem word read"));
-
- // ROM'd MAC address
- if ((address >=0) && (address <= 31)) {
- retval = BX_NE2K_THIS s.macaddr[address];
- if (io_len == 2) {
- retval |= (BX_NE2K_THIS s.macaddr[address + 1] << 8);
- }
- return (retval);
- }
-
- if ((address >= BX_NE2K_MEMSTART) && (address < BX_NE2K_MEMEND)) {
- retval = BX_NE2K_THIS s.mem[address - BX_NE2K_MEMSTART];
- if (io_len == 2) {
- retval |= (BX_NE2K_THIS s.mem[address - BX_NE2K_MEMSTART + 1] << 8);
- }
- return (retval);
- }
-
- BX_DEBUG(("out-of-bounds chipmem read, %04X", address));
-
- return (0xff);
-}
-
-void BX_CPP_AttrRegparmN(3)
-bx_ne2k_c::chipmem_write(Bit32u address, Bit32u value, unsigned io_len)
-{
- if ((io_len == 2) && (address & 0x1))
- BX_PANIC(("unaligned chipmem word write"));
-
- if ((address >= BX_NE2K_MEMSTART) && (address < BX_NE2K_MEMEND)) {
- BX_NE2K_THIS s.mem[address - BX_NE2K_MEMSTART] = value & 0xff;
- if (io_len == 2)
- BX_NE2K_THIS s.mem[address - BX_NE2K_MEMSTART + 1] = value >> 8;
- } else
- BX_DEBUG(("out-of-bounds chipmem write, %04X", address));
-}
-
-//
-// asic_read/asic_write - This is the high 16 bytes of i/o space
-// (the lower 16 bytes is for the DS8390). Only two locations
-// are used: offset 0, which is used for data transfer, and
-// offset 0xf, which is used to reset the device.
-// The data transfer port is used to as 'external' DMA to the
-// DS8390. The chip has to have the DMA registers set up, and
-// after that, insw/outsw instructions can be used to move
-// the appropriate number of bytes to/from the device.
-//
-Bit32u BX_CPP_AttrRegparmN(2)
-bx_ne2k_c::asic_read(Bit32u offset, unsigned int io_len)
-{
- Bit32u retval = 0;
-
- switch (offset) {
- case 0x0: // Data register
- //
- // A read remote-DMA command must have been issued,
- // and the source-address and length registers must
- // have been initialised.
- //
- if (io_len > BX_NE2K_THIS s.remote_bytes)
- {
- BX_ERROR(("ne2K: dma read underrun iolen=%d remote_bytes=%d",io_len,BX_NE2K_THIS s.remote_bytes));
- //return 0;
- }
-
- //BX_INFO(("ne2k read DMA: addr=%4x remote_bytes=%d",BX_NE2K_THIS s.remote_dma,BX_NE2K_THIS s.remote_bytes));
- retval = chipmem_read(BX_NE2K_THIS s.remote_dma, io_len);
- //
- // The 8390 bumps the address and decreases the byte count
- // by the selected word size after every access, not by
- // the amount of data requested by the host (io_len).
- //
- BX_NE2K_THIS s.remote_dma += (BX_NE2K_THIS s.DCR.wdsize + 1);
- if (BX_NE2K_THIS s.remote_dma == BX_NE2K_THIS s.page_stop << 8) {
- BX_NE2K_THIS s.remote_dma = BX_NE2K_THIS s.page_start << 8;
- }
- // keep s.remote_bytes from underflowing
- if (BX_NE2K_THIS s.remote_bytes > 1)
- BX_NE2K_THIS s.remote_bytes -= (BX_NE2K_THIS s.DCR.wdsize + 1);
- else
- BX_NE2K_THIS s.remote_bytes = 0;
-
- // If all bytes have been written, signal remote-DMA complete
- if (BX_NE2K_THIS s.remote_bytes == 0) {
- BX_NE2K_THIS s.ISR.rdma_done = 1;
- if (BX_NE2K_THIS s.IMR.rdma_inte) {
- DEV_pic_raise_irq(BX_NE2K_THIS s.base_irq);
- }
- }
- break;
-
- case 0xf: // Reset register
- theNE2kDevice->reset(BX_RESET_SOFTWARE);
- break;
-
- default:
- BX_INFO(("asic read invalid address %04x", (unsigned) offset));
- break;
- }
-
- return (retval);
-}
-
-void
-bx_ne2k_c::asic_write(Bit32u offset, Bit32u value, unsigned io_len)
-{
- BX_DEBUG(("asic write addr=0x%02x, value=0x%04x", (unsigned) offset, (unsigned) value));
- switch (offset) {
- case 0x0: // Data register - see asic_read for a description
-
- if ((io_len == 2) && (BX_NE2K_THIS s.DCR.wdsize == 0)) {
- BX_PANIC(("dma write length 2 on byte mode operation"));
- break;
- }
-
- if (BX_NE2K_THIS s.remote_bytes == 0)
- BX_PANIC(("ne2K: dma write, byte count 0"));
-
- chipmem_write(BX_NE2K_THIS s.remote_dma, value, io_len);
- // is this right ??? asic_read uses DCR.wordsize
- BX_NE2K_THIS s.remote_dma += io_len;
- if (BX_NE2K_THIS s.remote_dma == BX_NE2K_THIS s.page_stop << 8) {
- BX_NE2K_THIS s.remote_dma = BX_NE2K_THIS s.page_start << 8;
- }
-
- BX_NE2K_THIS s.remote_bytes -= io_len;
- if (BX_NE2K_THIS s.remote_bytes > BX_NE2K_MEMSIZ)
- BX_NE2K_THIS s.remote_bytes = 0;
-
- // If all bytes have been written, signal remote-DMA complete
- if (BX_NE2K_THIS s.remote_bytes == 0) {
- BX_NE2K_THIS s.ISR.rdma_done = 1;
- if (BX_NE2K_THIS s.IMR.rdma_inte) {
- DEV_pic_raise_irq(BX_NE2K_THIS s.base_irq);
- }
- }
- break;
-
- case 0xf: // Reset register
- theNE2kDevice->reset(BX_RESET_SOFTWARE);
- break;
-
- default: // this is invalid, but happens under win95 device detection
- BX_INFO(("asic write invalid address %04x, ignoring", (unsigned) offset));
- break ;
- }
-}
-
-//
-// page0_read/page0_write - These routines handle reads/writes to
-// the 'zeroth' page of the DS8390 register file
-//
-Bit32u
-bx_ne2k_c::page0_read(Bit32u offset, unsigned int io_len)
-{
- BX_DEBUG(("page 0 read from port %04x, len=%u", (unsigned) offset,
- (unsigned) io_len));
- if (io_len > 1) {
- BX_ERROR(("bad length! page 0 read from port %04x, len=%u", (unsigned) offset,
- (unsigned) io_len)); /* encountered with win98 hardware probe */
- return 0;
- }
-
-
- switch (offset) {
- case 0x0: // CR
- return (read_cr());
- break;
-
- case 0x1: // CLDA0
- return (BX_NE2K_THIS s.local_dma & 0xff);
- break;
-
- case 0x2: // CLDA1
- return (BX_NE2K_THIS s.local_dma >> 8);
- break;
-
- case 0x3: // BNRY
- return (BX_NE2K_THIS s.bound_ptr);
- break;
-
- case 0x4: // TSR
- return ((BX_NE2K_THIS s.TSR.ow_coll << 7) |
- (BX_NE2K_THIS s.TSR.cd_hbeat << 6) |
- (BX_NE2K_THIS s.TSR.fifo_ur << 5) |
- (BX_NE2K_THIS s.TSR.no_carrier << 4) |
- (BX_NE2K_THIS s.TSR.aborted << 3) |
- (BX_NE2K_THIS s.TSR.collided << 2) |
- (BX_NE2K_THIS s.TSR.tx_ok));
- break;
-
- case 0x5: // NCR
- return (BX_NE2K_THIS s.num_coll);
- break;
-
- case 0x6: // FIFO
- // reading FIFO is only valid in loopback mode
- BX_ERROR(("reading FIFO not supported yet"));
- return (BX_NE2K_THIS s.fifo);
- break;
-
- case 0x7: // ISR
- return ((BX_NE2K_THIS s.ISR.reset << 7) |
- (BX_NE2K_THIS s.ISR.rdma_done << 6) |
- (BX_NE2K_THIS s.ISR.cnt_oflow << 5) |
- (BX_NE2K_THIS s.ISR.overwrite << 4) |
- (BX_NE2K_THIS s.ISR.tx_err << 3) |
- (BX_NE2K_THIS s.ISR.rx_err << 2) |
- (BX_NE2K_THIS s.ISR.pkt_tx << 1) |
- (BX_NE2K_THIS s.ISR.pkt_rx));
- break;
-
- case 0x8: // CRDA0
- return (BX_NE2K_THIS s.remote_dma & 0xff);
- break;
-
- case 0x9: // CRDA1
- return (BX_NE2K_THIS s.remote_dma >> 8);
- break;
-
- case 0xa: // reserved
- BX_INFO(("reserved read - page 0, 0xa"));
- return (0xff);
- break;
-
- case 0xb: // reserved
- BX_INFO(("reserved read - page 0, 0xb"));
- return (0xff);
- break;
-
- case 0xc: // RSR
- return ((BX_NE2K_THIS s.RSR.deferred << 7) |
- (BX_NE2K_THIS s.RSR.rx_disabled << 6) |
- (BX_NE2K_THIS s.RSR.rx_mbit << 5) |
- (BX_NE2K_THIS s.RSR.rx_missed << 4) |
- (BX_NE2K_THIS s.RSR.fifo_or << 3) |
- (BX_NE2K_THIS s.RSR.bad_falign << 2) |
- (BX_NE2K_THIS s.RSR.bad_crc << 1) |
- (BX_NE2K_THIS s.RSR.rx_ok));
- break;
-
- case 0xd: // CNTR0
- return (BX_NE2K_THIS s.tallycnt_0);
- break;
-
- case 0xe: // CNTR1
- return (BX_NE2K_THIS s.tallycnt_1);
- break;
-
- case 0xf: // CNTR2
- return (BX_NE2K_THIS s.tallycnt_2);
- break;
-
- default:
- BX_PANIC(("page 0 offset %04x out of range", (unsigned) offset));
- }
-
- return(0);
-}
-
-void
-bx_ne2k_c::page0_write(Bit32u offset, Bit32u value, unsigned io_len)
-{
- BX_DEBUG(("page 0 write to port %04x, len=%u", (unsigned) offset,
- (unsigned) io_len));
-
- // It appears to be a common practice to use outw on page0 regs...
-
- // break up outw into two outb's
- if (io_len == 2) {
- page0_write(offset, (value & 0xff), 1);
- page0_write(offset + 1, ((value >> 8) & 0xff), 1);
- return;
- }
-
- switch (offset) {
- case 0x0: // CR
- write_cr(value);
- break;
-
- case 0x1: // PSTART
- BX_NE2K_THIS s.page_start = value;
- break;
-
- case 0x2: // PSTOP
- // BX_INFO(("Writing to PSTOP: %02x", value));
- BX_NE2K_THIS s.page_stop = value;
- break;
-
- case 0x3: // BNRY
- BX_NE2K_THIS s.bound_ptr = value;
- break;
-
- case 0x4: // TPSR
- BX_NE2K_THIS s.tx_page_start = value;
- break;
-
- case 0x5: // TBCR0
- // Clear out low byte and re-insert
- BX_NE2K_THIS s.tx_bytes &= 0xff00;
- BX_NE2K_THIS s.tx_bytes |= (value & 0xff);
- break;
-
- case 0x6: // TBCR1
- // Clear out high byte and re-insert
- BX_NE2K_THIS s.tx_bytes &= 0x00ff;
- BX_NE2K_THIS s.tx_bytes |= ((value & 0xff) << 8);
- break;
-
- case 0x7: // ISR
- value &= 0x7f; // clear RST bit - status-only bit
- // All other values are cleared iff the ISR bit is 1
- BX_NE2K_THIS s.ISR.pkt_rx &= ~((bx_bool)((value & 0x01) == 0x01));
- BX_NE2K_THIS s.ISR.pkt_tx &= ~((bx_bool)((value & 0x02) == 0x02));
- BX_NE2K_THIS s.ISR.rx_err &= ~((bx_bool)((value & 0x04) == 0x04));
- BX_NE2K_THIS s.ISR.tx_err &= ~((bx_bool)((value & 0x08) == 0x08));
- BX_NE2K_THIS s.ISR.overwrite &= ~((bx_bool)((value & 0x10) == 0x10));
- BX_NE2K_THIS s.ISR.cnt_oflow &= ~((bx_bool)((value & 0x20) == 0x20));
- BX_NE2K_THIS s.ISR.rdma_done &= ~((bx_bool)((value & 0x40) == 0x40));
- value = ((BX_NE2K_THIS s.ISR.rdma_done << 6) |
- (BX_NE2K_THIS s.ISR.cnt_oflow << 5) |
- (BX_NE2K_THIS s.ISR.overwrite << 4) |
- (BX_NE2K_THIS s.ISR.tx_err << 3) |
- (BX_NE2K_THIS s.ISR.rx_err << 2) |
- (BX_NE2K_THIS s.ISR.pkt_tx << 1) |
- (BX_NE2K_THIS s.ISR.pkt_rx));
- value &= ((BX_NE2K_THIS s.IMR.rdma_inte << 6) |
- (BX_NE2K_THIS s.IMR.cofl_inte << 5) |
- (BX_NE2K_THIS s.IMR.overw_inte << 4) |
- (BX_NE2K_THIS s.IMR.txerr_inte << 3) |
- (BX_NE2K_THIS s.IMR.rxerr_inte << 2) |
- (BX_NE2K_THIS s.IMR.tx_inte << 1) |
- (BX_NE2K_THIS s.IMR.rx_inte));
- if (value == 0)
- DEV_pic_lower_irq(BX_NE2K_THIS s.base_irq);
- break;
-
- case 0x8: // RSAR0
- // Clear out low byte and re-insert
- BX_NE2K_THIS s.remote_start &= 0xff00;
- BX_NE2K_THIS s.remote_start |= (value & 0xff);
- BX_NE2K_THIS s.remote_dma = BX_NE2K_THIS s.remote_start;
- break;
-
- case 0x9: // RSAR1
- // Clear out high byte and re-insert
- BX_NE2K_THIS s.remote_start &= 0x00ff;
- BX_NE2K_THIS s.remote_start |= ((value & 0xff) << 8);
- BX_NE2K_THIS s.remote_dma = BX_NE2K_THIS s.remote_start;
- break;
-
- case 0xa: // RBCR0
- // Clear out low byte and re-insert
- BX_NE2K_THIS s.remote_bytes &= 0xff00;
- BX_NE2K_THIS s.remote_bytes |= (value & 0xff);
- break;
-
- case 0xb: // RBCR1
- // Clear out high byte and re-insert
- BX_NE2K_THIS s.remote_bytes &= 0x00ff;
- BX_NE2K_THIS s.remote_bytes |= ((value & 0xff) << 8);
- break;
-
- case 0xc: // RCR
- // Check if the reserved bits are set
- if (value & 0xc0)
- BX_INFO(("RCR write, reserved bits set"));
-
- // Set all other bit-fields
- BX_NE2K_THIS s.RCR.errors_ok = ((value & 0x01) == 0x01);
- BX_NE2K_THIS s.RCR.runts_ok = ((value & 0x02) == 0x02);
- BX_NE2K_THIS s.RCR.broadcast = ((value & 0x04) == 0x04);
- BX_NE2K_THIS s.RCR.multicast = ((value & 0x08) == 0x08);
- BX_NE2K_THIS s.RCR.promisc = ((value & 0x10) == 0x10);
- BX_NE2K_THIS s.RCR.monitor = ((value & 0x20) == 0x20);
-
- // Monitor bit is a little suspicious...
- if (value & 0x20)
- BX_INFO(("RCR write, monitor bit set!"));
- break;
-
- case 0xd: // TCR
- // Check reserved bits
- if (value & 0xe0)
- BX_ERROR(("TCR write, reserved bits set"));
-
- // Test loop mode (not supported)
- if (value & 0x06) {
- BX_NE2K_THIS s.TCR.loop_cntl = (value & 0x6) >> 1;
- BX_INFO(("TCR write, loop mode %d not supported", BX_NE2K_THIS s.TCR.loop_cntl));
- } else {
- BX_NE2K_THIS s.TCR.loop_cntl = 0;
- }
-
- // Inhibit-CRC not supported.
- if (value & 0x01)
- BX_PANIC(("TCR write, inhibit-CRC not supported"));
-
- // Auto-transmit disable very suspicious
- if (value & 0x08)
- BX_PANIC(("TCR write, auto transmit disable not supported"));
-
- // Allow collision-offset to be set, although not used
- BX_NE2K_THIS s.TCR.coll_prio = ((value & 0x08) == 0x08);
- break;
-
- case 0xe: // DCR
- // the loopback mode is not suppported yet
- if (!(value & 0x08)) {
- BX_ERROR(("DCR write, loopback mode selected"));
- }
- // It is questionable to set longaddr and auto_rx, since they
- // aren't supported on the ne2000. Print a warning and continue
- if (value & 0x04)
- BX_INFO(("DCR write - LAS set ???"));
- if (value & 0x10)
- BX_INFO(("DCR write - AR set ???"));
-
- // Set other values.
- BX_NE2K_THIS s.DCR.wdsize = ((value & 0x01) == 0x01);
- BX_NE2K_THIS s.DCR.endian = ((value & 0x02) == 0x02);
- BX_NE2K_THIS s.DCR.longaddr = ((value & 0x04) == 0x04); // illegal ?
- BX_NE2K_THIS s.DCR.loop = ((value & 0x08) == 0x08);
- BX_NE2K_THIS s.DCR.auto_rx = ((value & 0x10) == 0x10); // also illegal ?
- BX_NE2K_THIS s.DCR.fifo_size = (value & 0x50) >> 5;
- break;
-
- case 0xf: // IMR
- // Check for reserved bit
- if (value & 0x80)
- BX_PANIC(("IMR write, reserved bit set"));
-
- // Set other values
- BX_NE2K_THIS s.IMR.rx_inte = ((value & 0x01) == 0x01);
- BX_NE2K_THIS s.IMR.tx_inte = ((value & 0x02) == 0x02);
- BX_NE2K_THIS s.IMR.rxerr_inte = ((value & 0x04) == 0x04);
- BX_NE2K_THIS s.IMR.txerr_inte = ((value & 0x08) == 0x08);
- BX_NE2K_THIS s.IMR.overw_inte = ((value & 0x10) == 0x10);
- BX_NE2K_THIS s.IMR.cofl_inte = ((value & 0x20) == 0x20);
- BX_NE2K_THIS s.IMR.rdma_inte = ((value & 0x40) == 0x40);
- break;
-
- default:
- BX_PANIC(("page 0 write, bad offset %0x", offset));
- }
-}
-
-
-//
-// page1_read/page1_write - These routines handle reads/writes to
-// the first page of the DS8390 register file
-//
-Bit32u
-bx_ne2k_c::page1_read(Bit32u offset, unsigned int io_len)
-{
- BX_DEBUG(("page 1 read from port %04x, len=%u", (unsigned) offset,
- (unsigned) io_len));
- if (io_len > 1)
- BX_PANIC(("bad length! page 1 read from port %04x, len=%u", (unsigned) offset,
- (unsigned) io_len));
-
- switch (offset) {
- case 0x0: // CR
- return (read_cr());
- break;
-
- case 0x1: // PAR0-5
- case 0x2:
- case 0x3:
- case 0x4:
- case 0x5:
- case 0x6:
- return (BX_NE2K_THIS s.physaddr[offset - 1]);
- break;
-
- case 0x7: // CURR
- BX_DEBUG(("returning current page: %02x", (BX_NE2K_THIS s.curr_page)));
- return (BX_NE2K_THIS s.curr_page);
-
- case 0x8: // MAR0-7
- case 0x9:
- case 0xa:
- case 0xb:
- case 0xc:
- case 0xd:
- case 0xe:
- case 0xf:
- return (BX_NE2K_THIS s.mchash[offset - 8]);
- break;
-
- default:
- BX_PANIC(("page 1 r offset %04x out of range", (unsigned) offset));
- }
-
- return (0);
-}
-
-void
-bx_ne2k_c::page1_write(Bit32u offset, Bit32u value, unsigned io_len)
-{
- BX_DEBUG(("page 1 w offset %04x", (unsigned) offset));
- switch (offset) {
- case 0x0: // CR
- write_cr(value);
- break;
-
- case 0x1: // PAR0-5
- case 0x2:
- case 0x3:
- case 0x4:
- case 0x5:
- case 0x6:
- BX_NE2K_THIS s.physaddr[offset - 1] = value;
- break;
-
- case 0x7: // CURR
- BX_NE2K_THIS s.curr_page = value;
- break;
-
- case 0x8: // MAR0-7
- case 0x9:
- case 0xa:
- case 0xb:
- case 0xc:
- case 0xd:
- case 0xe:
- case 0xf:
- BX_NE2K_THIS s.mchash[offset - 8] = value;
- break;
-
- default:
- BX_PANIC(("page 1 w offset %04x out of range", (unsigned) offset));
- }
-}
-
-
-//
-// page2_read/page2_write - These routines handle reads/writes to
-// the second page of the DS8390 register file
-//
-Bit32u
-bx_ne2k_c::page2_read(Bit32u offset, unsigned int io_len)
-{
- BX_DEBUG(("page 2 read from port %04x, len=%u", (unsigned) offset, (unsigned) io_len));
-
- if (io_len > 1)
- BX_PANIC(("bad length! page 2 read from port %04x, len=%u", (unsigned) offset, (unsigned) io_len));
-
- switch (offset) {
- case 0x0: // CR
- return (read_cr());
- break;
-
- case 0x1: // PSTART
- return (BX_NE2K_THIS s.page_start);
- break;
-
- case 0x2: // PSTOP
- return (BX_NE2K_THIS s.page_stop);
- break;
-
- case 0x3: // Remote Next-packet pointer
- return (BX_NE2K_THIS s.rempkt_ptr);
- break;
-
- case 0x4: // TPSR
- return (BX_NE2K_THIS s.tx_page_start);
- break;
-
- case 0x5: // Local Next-packet pointer
- return (BX_NE2K_THIS s.localpkt_ptr);
- break;
-
- case 0x6: // Address counter (upper)
- return (BX_NE2K_THIS s.address_cnt >> 8);
- break;
-
- case 0x7: // Address counter (lower)
- return (BX_NE2K_THIS s.address_cnt & 0xff);
- break;
-
- case 0x8: // Reserved
- case 0x9:
- case 0xa:
- case 0xb:
- BX_ERROR(("reserved read - page 2, 0x%02x", (unsigned) offset));
- return (0xff);
- break;
-
- case 0xc: // RCR
- return ((BX_NE2K_THIS s.RCR.monitor << 5) |
- (BX_NE2K_THIS s.RCR.promisc << 4) |
- (BX_NE2K_THIS s.RCR.multicast << 3) |
- (BX_NE2K_THIS s.RCR.broadcast << 2) |
- (BX_NE2K_THIS s.RCR.runts_ok << 1) |
- (BX_NE2K_THIS s.RCR.errors_ok));
- break;
-
- case 0xd: // TCR
- return ((BX_NE2K_THIS s.TCR.coll_prio << 4) |
- (BX_NE2K_THIS s.TCR.ext_stoptx << 3) |
- ((BX_NE2K_THIS s.TCR.loop_cntl & 0x3) << 1) |
- (BX_NE2K_THIS s.TCR.crc_disable));
- break;
-
- case 0xe: // DCR
- return (((BX_NE2K_THIS s.DCR.fifo_size & 0x3) << 5) |
- (BX_NE2K_THIS s.DCR.auto_rx << 4) |
- (BX_NE2K_THIS s.DCR.loop << 3) |
- (BX_NE2K_THIS s.DCR.longaddr << 2) |
- (BX_NE2K_THIS s.DCR.endian << 1) |
- (BX_NE2K_THIS s.DCR.wdsize));
- break;
-
- case 0xf: // IMR
- return ((BX_NE2K_THIS s.IMR.rdma_inte << 6) |
- (BX_NE2K_THIS s.IMR.cofl_inte << 5) |
- (BX_NE2K_THIS s.IMR.overw_inte << 4) |
- (BX_NE2K_THIS s.IMR.txerr_inte << 3) |
- (BX_NE2K_THIS s.IMR.rxerr_inte << 2) |
- (BX_NE2K_THIS s.IMR.tx_inte << 1) |
- (BX_NE2K_THIS s.IMR.rx_inte));
- break;
-
- default:
- BX_PANIC(("page 2 offset %04x out of range", (unsigned) offset));
- }
-
- return (0);
-};
-
-void
-bx_ne2k_c::page2_write(Bit32u offset, Bit32u value, unsigned io_len)
-{
- // Maybe all writes here should be BX_PANIC()'d, since they
- // affect internal operation, but let them through for now
- // and print a warning.
- if (offset != 0)
- BX_ERROR(("page 2 write ?"));
-
- switch (offset) {
- case 0x0: // CR
- write_cr(value);
- break;
-
- case 0x1: // CLDA0
- // Clear out low byte and re-insert
- BX_NE2K_THIS s.local_dma &= 0xff00;
- BX_NE2K_THIS s.local_dma |= (value & 0xff);
- break;
-
- case 0x2: // CLDA1
- // Clear out high byte and re-insert
- BX_NE2K_THIS s.local_dma &= 0x00ff;
- BX_NE2K_THIS s.local_dma |= ((value & 0xff) << 8);
- break;
-
- case 0x3: // Remote Next-pkt pointer
- BX_NE2K_THIS s.rempkt_ptr = value;
- break;
-
- case 0x4:
- BX_PANIC(("page 2 write to reserved offset 4"));
- break;
-
- case 0x5: // Local Next-packet pointer
- BX_NE2K_THIS s.localpkt_ptr = value;
- break;
-
- case 0x6: // Address counter (upper)
- // Clear out high byte and re-insert
- BX_NE2K_THIS s.address_cnt &= 0x00ff;
- BX_NE2K_THIS s.address_cnt |= ((value & 0xff) << 8);
- break;
-
- case 0x7: // Address counter (lower)
- // Clear out low byte and re-insert
- BX_NE2K_THIS s.address_cnt &= 0xff00;
- BX_NE2K_THIS s.address_cnt |= (value & 0xff);
- break;
-
- case 0x8:
- case 0x9:
- case 0xa:
- case 0xb:
- case 0xc:
- case 0xd:
- case 0xe:
- case 0xf:
- BX_PANIC(("page 2 write to reserved offset %0x", offset));
- break;
-
- default:
- BX_PANIC(("page 2 write, illegal offset %0x", offset));
- break;
- }
-}
-
-//
-// page3_read/page3_write - writes to this page are illegal
-//
-Bit32u
-bx_ne2k_c::page3_read(Bit32u offset, unsigned int io_len)
-{
- BX_PANIC(("page 3 read attempted"));
- return (0);
-}
-
-void
-bx_ne2k_c::page3_write(Bit32u offset, Bit32u value, unsigned io_len)
-{
- BX_PANIC(("page 3 write attempted"));
-}
-
-//
-// tx_timer_handler/tx_timer
-//
-void
-bx_ne2k_c::tx_timer_handler(void *this_ptr)
-{
- bx_ne2k_c *class_ptr = (bx_ne2k_c *) this_ptr;
-
- class_ptr->tx_timer();
-}
-
-void
-bx_ne2k_c::tx_timer(void)
-{
- BX_DEBUG(("tx_timer"));
- BX_NE2K_THIS s.TSR.tx_ok = 1;
- // Generate an interrupt if not masked and not one in progress
- if (BX_NE2K_THIS s.IMR.tx_inte && !BX_NE2K_THIS s.ISR.pkt_tx) {
- BX_NE2K_THIS s.ISR.pkt_tx = 1;
- DEV_pic_raise_irq(BX_NE2K_THIS s.base_irq);
- }
- BX_NE2K_THIS s.tx_timer_active = 0;
-}
-
-
-//
-// read_handler/read - i/o 'catcher' function called from BOCHS
-// mainline when the CPU attempts a read in the i/o space registered
-// by this ne2000 instance
-//
-Bit32u
-bx_ne2k_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len)
-{
-#if !BX_USE_NE2K_SMF
- bx_ne2k_c *class_ptr = (bx_ne2k_c *) this_ptr;
-
- return( class_ptr->read(address, io_len) );
-}
-
-Bit32u
-bx_ne2k_c::read(Bit32u address, unsigned io_len)
-{
-#else
- UNUSED(this_ptr);
-#endif // !BX_USE_NE2K_SMF
- BX_DEBUG(("read addr %x, len %d", address, io_len));
- Bit32u retval = 0;
- int offset = address - BX_NE2K_THIS s.base_address;
-
- if (offset >= 0x10) {
- retval = asic_read(offset - 0x10, io_len);
- } else {
- switch (BX_NE2K_THIS s.CR.pgsel) {
- case 0x00:
- retval = page0_read(offset, io_len);
- break;
-
- case 0x01:
- retval = page1_read(offset, io_len);
- break;
-
- case 0x02:
- retval = page2_read(offset, io_len);
- break;
-
- case 0x03:
- retval = page3_read(offset, io_len);
- break;
-
- default:
- BX_PANIC(("ne2K: unknown value of pgsel in read - %d",
- BX_NE2K_THIS s.CR.pgsel));
- }
- }
-
- return (retval);
-}
-
-//
-// write_handler/write - i/o 'catcher' function called from BOCHS
-// mainline when the CPU attempts a write in the i/o space registered
-// by this ne2000 instance
-//
-void
-bx_ne2k_c::write_handler(void *this_ptr, Bit32u address, Bit32u value,
- unsigned io_len)
-{
-#if !BX_USE_NE2K_SMF
- bx_ne2k_c *class_ptr = (bx_ne2k_c *) this_ptr;
-
- class_ptr->write(address, value, io_len);
-}
-
-void
-bx_ne2k_c::write(Bit32u address, Bit32u value, unsigned io_len)
-{
-#else
- UNUSED(this_ptr);
-#endif // !BX_USE_NE2K_SMF
- BX_DEBUG(("write with length %d", io_len));
- int offset = address - BX_NE2K_THIS s.base_address;
-
- //
- // The high 16 bytes of i/o space are for the ne2000 asic -
- // the low 16 bytes are for the DS8390, with the current
- // page being selected by the PS0,PS1 registers in the
- // command register
- //
- if (offset >= 0x10) {
- asic_write(offset - 0x10, value, io_len);
- } else {
- switch (BX_NE2K_THIS s.CR.pgsel) {
- case 0x00:
- page0_write(offset, value, io_len);
- break;
-
- case 0x01:
- page1_write(offset, value, io_len);
- break;
-
- case 0x02:
- page2_write(offset, value, io_len);
- break;
-
- case 0x03:
- page3_write(offset, value, io_len);
- break;
-
- default:
- BX_PANIC(("ne2K: unknown value of pgsel in write - %d",
- BX_NE2K_THIS s.CR.pgsel));
- }
- }
-}
-
-
-/*
- * mcast_index() - return the 6-bit index into the multicast
- * table. Stolen unashamedly from FreeBSD's if_ed.c
- */
-unsigned
-bx_ne2k_c::mcast_index(const void *dst)
-{
-#define POLYNOMIAL 0x04c11db6
- unsigned long crc = 0xffffffffL;
- int carry, i, j;
- unsigned char b;
- unsigned char *ep = (unsigned char *) dst;
-
- for (i = 6; --i >= 0;) {
- b = *ep++;
- for (j = 8; --j >= 0;) {
- carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01);
- crc <<= 1;
- b >>= 1;
- if (carry)
- crc = ((crc ^ POLYNOMIAL) | carry);
- }
- }
- return (crc >> 26);
-#undef POLYNOMIAL
-}
-
-/*
- * Callback from the eth system driver when a frame has arrived
- */
-void
-bx_ne2k_c::rx_handler(void *arg, const void *buf, unsigned len)
-{
- // BX_DEBUG(("rx_handler with length %d", len));
- bx_ne2k_c *class_ptr = (bx_ne2k_c *) arg;
-
- class_ptr->rx_frame(buf, len);
-}
-
-/*
- * rx_frame() - called by the platform-specific code when an
- * ethernet frame has been received. The destination address
- * is tested to see if it should be accepted, and if the
- * rx ring has enough room, it is copied into it and
- * the receive process is updated
- */
-void
-bx_ne2k_c::rx_frame(const void *buf, unsigned io_len)
-{
- unsigned pages;
- unsigned avail;
- unsigned idx;
- int wrapped;
- int nextpage;
- unsigned char pkthdr[4];
- unsigned char *pktbuf = (unsigned char *) buf;
- unsigned char *startptr;
- static unsigned char bcast_addr[6] = {0xff,0xff,0xff,0xff,0xff,0xff};
-
- BX_DEBUG(("rx_frame with length %d", io_len));
-
-
- if ((BX_NE2K_THIS s.CR.stop != 0) ||
- (BX_NE2K_THIS s.page_start == 0) ||
- ((BX_NE2K_THIS s.DCR.loop == 0) &&
- (BX_NE2K_THIS s.TCR.loop_cntl != 0))) {
-
- return;
- }
-
- // Add the pkt header + CRC to the length, and work
- // out how many 256-byte pages the frame would occupy
- pages = (io_len + 4 + 4 + 255)/256;
-
- if (BX_NE2K_THIS s.curr_page < BX_NE2K_THIS s.bound_ptr) {
- avail = BX_NE2K_THIS s.bound_ptr - BX_NE2K_THIS s.curr_page;
- } else {
- avail = (BX_NE2K_THIS s.page_stop - BX_NE2K_THIS s.page_start) -
- (BX_NE2K_THIS s.curr_page - BX_NE2K_THIS s.bound_ptr);
- wrapped = 1;
- }
-
- // Avoid getting into a buffer overflow condition by not attempting
- // to do partial receives. The emulation to handle this condition
- // seems particularly painful.
- if ((avail < pages)
-#if BX_NE2K_NEVER_FULL_RING
- || (avail == pages)
-#endif
- ) {
- return;
- }
-
- if ((io_len < 60) && !BX_NE2K_THIS s.RCR.runts_ok) {
- BX_DEBUG(("rejected small packet, length %d", io_len));
- return;
- }
-
- // Do address filtering if not in promiscuous mode
- if (! BX_NE2K_THIS s.RCR.promisc) {
- if (!memcmp(buf, bcast_addr, 6)) {
- if (!BX_NE2K_THIS s.RCR.broadcast) {
- return;
- }
- } else if (pktbuf[0] & 0x01) {
- if (! BX_NE2K_THIS s.RCR.multicast) {
- return;
- }
- idx = mcast_index(buf);
- if (!(BX_NE2K_THIS s.mchash[idx >> 3] & (1 << (idx & 0x7)))) {
- return;
- }
- } else if (0 != memcmp(buf, BX_NE2K_THIS s.physaddr, 6)) {
- return;
- }
- } else {
- BX_DEBUG(("rx_frame promiscuous receive"));
- }
-
-// BX_INFO(("rx_frame %d to %x:%x:%x:%x:%x:%x from %x:%x:%x:%x:%x:%x",
-// io_len,
-// pktbuf[0], pktbuf[1], pktbuf[2], pktbuf[3], pktbuf[4], pktbuf[5],
-// pktbuf[6], pktbuf[7], pktbuf[8], pktbuf[9], pktbuf[10], pktbuf[11]));
-
- nextpage = BX_NE2K_THIS s.curr_page + pages;
- if (nextpage >= BX_NE2K_THIS s.page_stop) {
- nextpage -= BX_NE2K_THIS s.page_stop - BX_NE2K_THIS s.page_start;
- }
-
- // Setup packet header
- pkthdr[0] = 0; // rx status - old behavior
- pkthdr[0] = 1; // Probably better to set it all the time
- // rather than set it to 0, which is clearly wrong.
- if (pktbuf[0] & 0x01) {
- pkthdr[0] |= 0x20; // rx status += multicast packet
- }
- pkthdr[1] = nextpage; // ptr to next packet
- pkthdr[2] = (io_len + 4) & 0xff; // length-low
- pkthdr[3] = (io_len + 4) >> 8; // length-hi
-
- // copy into buffer, update curpage, and signal interrupt if config'd
- startptr = & BX_NE2K_THIS s.mem[BX_NE2K_THIS s.curr_page * 256 -
- BX_NE2K_MEMSTART];
- if ((nextpage > BX_NE2K_THIS s.curr_page) ||
- ((BX_NE2K_THIS s.curr_page + pages) == BX_NE2K_THIS s.page_stop)) {
- memcpy(startptr, pkthdr, 4);
- memcpy(startptr + 4, buf, io_len);
- BX_NE2K_THIS s.curr_page = nextpage;
- } else {
- int endbytes = (BX_NE2K_THIS s.page_stop - BX_NE2K_THIS s.curr_page)
- * 256;
- memcpy(startptr, pkthdr, 4);
- memcpy(startptr + 4, buf, endbytes - 4);
- startptr = & BX_NE2K_THIS s.mem[BX_NE2K_THIS s.page_start * 256 -
- BX_NE2K_MEMSTART];
- memcpy(startptr, (void *)(pktbuf + endbytes - 4),
- io_len - endbytes + 8);
- BX_NE2K_THIS s.curr_page = nextpage;
- }
-
- BX_NE2K_THIS s.RSR.rx_ok = 1;
- if (pktbuf[0] & 0x80) {
- BX_NE2K_THIS s.RSR.rx_mbit = 1;
- }
-
- BX_NE2K_THIS s.ISR.pkt_rx = 1;
-
- if (BX_NE2K_THIS s.IMR.rx_inte) {
- DEV_pic_raise_irq(BX_NE2K_THIS s.base_irq);
- }
-
-}
-
-void
-bx_ne2k_c::init(void)
-{
- BX_DEBUG(("Init $Id: ne2k.cc,v 1.56.2.1 2004/02/02 22:37:22 cbothamy Exp $"));
-
- // Read in values from config file
- BX_NE2K_THIS s.base_address = bx_options.ne2k.Oioaddr->get ();
- BX_NE2K_THIS s.base_irq = bx_options.ne2k.Oirq->get ();
- memcpy(BX_NE2K_THIS s.physaddr, bx_options.ne2k.Omacaddr->getptr (), 6);
-
- if (BX_NE2K_THIS s.tx_timer_index == BX_NULL_TIMER_HANDLE) {
- BX_NE2K_THIS s.tx_timer_index =
- bx_pc_system.register_timer(this, tx_timer_handler, 0,
- 0,0, "ne2k"); // one-shot, inactive
- }
- // Register the IRQ and i/o port addresses
- DEV_register_irq(BX_NE2K_THIS s.base_irq, "NE2000 ethernet NIC");
-
- for (unsigned addr = BX_NE2K_THIS s.base_address;
- addr <= BX_NE2K_THIS s.base_address + 0x20;
- addr++) {
- DEV_register_ioread_handler(this, read_handler, addr, "ne2000 NIC", 3);
- DEV_register_iowrite_handler(this, write_handler, addr, "ne2000 NIC", 3);
- }
- BX_INFO(("port 0x%x/32 irq %d mac %02x:%02x:%02x:%02x:%02x:%02x",
- BX_NE2K_THIS s.base_address,
- BX_NE2K_THIS s.base_irq,
- BX_NE2K_THIS s.physaddr[0],
- BX_NE2K_THIS s.physaddr[1],
- BX_NE2K_THIS s.physaddr[2],
- BX_NE2K_THIS s.physaddr[3],
- BX_NE2K_THIS s.physaddr[4],
- BX_NE2K_THIS s.physaddr[5]));
-
- // Initialise the mac address area by doubling the physical address
- BX_NE2K_THIS s.macaddr[0] = BX_NE2K_THIS s.physaddr[0];
- BX_NE2K_THIS s.macaddr[1] = BX_NE2K_THIS s.physaddr[0];
- BX_NE2K_THIS s.macaddr[2] = BX_NE2K_THIS s.physaddr[1];
- BX_NE2K_THIS s.macaddr[3] = BX_NE2K_THIS s.physaddr[1];
- BX_NE2K_THIS s.macaddr[4] = BX_NE2K_THIS s.physaddr[2];
- BX_NE2K_THIS s.macaddr[5] = BX_NE2K_THIS s.physaddr[2];
- BX_NE2K_THIS s.macaddr[6] = BX_NE2K_THIS s.physaddr[3];
- BX_NE2K_THIS s.macaddr[7] = BX_NE2K_THIS s.physaddr[3];
- BX_NE2K_THIS s.macaddr[8] = BX_NE2K_THIS s.physaddr[4];
- BX_NE2K_THIS s.macaddr[9] = BX_NE2K_THIS s.physaddr[4];
- BX_NE2K_THIS s.macaddr[10] = BX_NE2K_THIS s.physaddr[5];
- BX_NE2K_THIS s.macaddr[11] = BX_NE2K_THIS s.physaddr[5];
-
- // ne2k signature
- for (int i = 12; i < 32; i++)
- BX_NE2K_THIS s.macaddr[i] = 0x57;
-
- // Attach to the simulated ethernet dev
- char *ethmod = bx_options.ne2k.Oethmod->get_choice(bx_options.ne2k.Oethmod->get());
- BX_NE2K_THIS ethdev = eth_locator_c::create(ethmod,
- bx_options.ne2k.Oethdev->getptr (),
- (const char *) bx_options.ne2k.Omacaddr->getptr (),
- rx_handler,
- this);
-
- if (BX_NE2K_THIS ethdev == NULL) {
- BX_PANIC(("could not find eth module %s", ethmod));
- // if they continue, use null.
- BX_INFO(("could not find eth module %s - using null instead", ethmod));
-
- BX_NE2K_THIS ethdev = eth_locator_c::create("null", NULL,
- (const char *) bx_options.ne2k.Omacaddr->getptr (),
- rx_handler,
- this);
- if (BX_NE2K_THIS ethdev == NULL)
- BX_PANIC(("could not locate null module"));
- }
-
- // Bring the register state into power-up state
- theNE2kDevice->reset(BX_RESET_HARDWARE);
-}
-
-#if BX_DEBUGGER
-
-/*
- * this implements the info ne2k commands in the debugger.
- * info ne2k - shows all registers
- * info ne2k page N - shows all registers in a page
- * info ne2k page N reg M - shows just one register
- */
-
-#define SHOW_FIELD(reg,field) do { \
- if (n>0 && !(n%5)) dbg_printf ("\n "); \
- dbg_printf ("%s=%d ", #field, BX_NE2K_THIS s.reg.field); \
- n++; \
-} while (0);
-#define BX_HIGH_BYTE(x) ((0xff00 & (x)) >> 8)
-#define BX_LOW_BYTE(x) (0x00ff & (x))
-#define BX_DUPLICATE(n) if (brief && num!=n) break;
-
-void
-bx_ne2k_c::print_info (FILE *fp, int page, int reg, int brief)
-{
- int i;
- int n = 0;
- if (page < 0) {
- for (page=0; page<=2; page++)
- theNE2kDevice->print_info (fp, page, reg, 1);
- // tell them how to use this command
- dbg_printf ("\nHow to use the info ne2k command:\n");
- dbg_printf ("info ne2k - show all registers\n");
- dbg_printf ("info ne2k page N - show registers in page N\n");
- dbg_printf ("info ne2k page N reg M - show just one register\n");
- return;
- }
- if (page > 2) {
- dbg_printf ("NE2K has only pages 0, 1, and 2. Page %d is out of range.\n", page);
- return;
- }
- if (reg < 0) {
- dbg_printf ("NE2K registers, page %d\n", page);
- dbg_printf ("----------------------\n");
- for (reg=0; reg<=15; reg++)
- theNE2kDevice->print_info (fp, page, reg, 1);
- dbg_printf ("----------------------\n");
- return;
- }
- if (reg > 15) {
- dbg_printf ("NE2K has only registers 0-15 (0x0-0xf). Register %d is out of range.\n", reg);
- return;
- }
- if (!brief) {
- dbg_printf ("NE2K Info - page %d, register 0x%02x\n", page, reg);
- dbg_printf ("----------------------------------\n");
- }
- int num = page*0x100 + reg;
- switch (num) {
- case 0x0000:
- case 0x0100:
- case 0x0200:
- dbg_printf ("CR (Command register):\n ");
- SHOW_FIELD (CR, stop);
- SHOW_FIELD (CR, start);
- SHOW_FIELD (CR, tx_packet);
- SHOW_FIELD (CR, rdma_cmd);
- SHOW_FIELD (CR, pgsel);
- dbg_printf ("\n");
- break;
- case 0x0003:
- dbg_printf ("BNRY = Boundary Pointer = 0x%02x\n", BX_NE2K_THIS s.bound_ptr);
- break;
- case 0x0004:
- dbg_printf ("TSR (Transmit Status Register), read-only:\n ");
- SHOW_FIELD (TSR, tx_ok);
- SHOW_FIELD (TSR, reserved);
- SHOW_FIELD (TSR, collided);
- SHOW_FIELD (TSR, aborted);
- SHOW_FIELD (TSR, no_carrier);
- SHOW_FIELD (TSR, fifo_ur);
- SHOW_FIELD (TSR, cd_hbeat);
- SHOW_FIELD (TSR, ow_coll);
- dbg_printf ("\n");
- // fall through into TPSR, no break line.
- case 0x0204:
- dbg_printf ("TPSR = Transmit Page Start = 0x%02x\n", BX_NE2K_THIS s.tx_page_start);
- break;
- case 0x0005:
- case 0x0006: BX_DUPLICATE(0x0005);
- dbg_printf ("NCR = Number of Collisions Register (read-only) = 0x%02x\n", BX_NE2K_THIS s.num_coll);
- dbg_printf ("TBCR1,TBCR0 = Transmit Byte Count = %02x %02x\n",
- BX_HIGH_BYTE (BX_NE2K_THIS s.tx_bytes),
- BX_LOW_BYTE (BX_NE2K_THIS s.tx_bytes));
- dbg_printf ("FIFO = %02x\n", BX_NE2K_THIS s.fifo);
- break;
- case 0x0007:
- dbg_printf ("ISR (Interrupt Status Register):\n ");
- SHOW_FIELD (ISR, pkt_rx);
- SHOW_FIELD (ISR, pkt_tx);
- SHOW_FIELD (ISR, rx_err);
- SHOW_FIELD (ISR, tx_err);
- SHOW_FIELD (ISR, overwrite);
- SHOW_FIELD (ISR, cnt_oflow);
- SHOW_FIELD (ISR, rdma_done);
- SHOW_FIELD (ISR, reset);
- dbg_printf ("\n");
- break;
- case 0x0008:
- case 0x0009: BX_DUPLICATE(0x0008);
- dbg_printf ("CRDA1,0 = Current remote DMA address = %02x %02x\n",
- BX_HIGH_BYTE (BX_NE2K_THIS s.remote_dma),
- BX_LOW_BYTE (BX_NE2K_THIS s.remote_dma));
- dbg_printf ("RSAR1,0 = Remote start address = %02x %02x\n",
- BX_HIGH_BYTE(s.remote_start),
- BX_LOW_BYTE(s.remote_start));
- break;
- case 0x000a:
- case 0x000b: BX_DUPLICATE(0x000a);
- dbg_printf ("RCBR1,0 = Remote byte count = %02x\n", BX_NE2K_THIS s.remote_bytes);
- break;
- case 0x000c:
- dbg_printf ("RSR (Receive Status Register), read-only:\n ");
- SHOW_FIELD (RSR, rx_ok);
- SHOW_FIELD (RSR, bad_crc);
- SHOW_FIELD (RSR, bad_falign);
- SHOW_FIELD (RSR, fifo_or);
- SHOW_FIELD (RSR, rx_missed);
- SHOW_FIELD (RSR, rx_mbit);
- SHOW_FIELD (RSR, rx_disabled);
- SHOW_FIELD (RSR, deferred);
- dbg_printf ("\n");
- // fall through into RCR
- case 0x020c:
- dbg_printf ("RCR (Receive Configuration Register):\n ");
- SHOW_FIELD (RCR, errors_ok);
- SHOW_FIELD (RCR, runts_ok);
- SHOW_FIELD (RCR, broadcast);
- SHOW_FIELD (RCR, multicast);
- SHOW_FIELD (RCR, promisc);
- SHOW_FIELD (RCR, monitor);
- SHOW_FIELD (RCR, reserved);
- dbg_printf ("\n");
- break;
- case 0x000d:
- dbg_printf ("CNTR0 = Tally Counter 0 (Frame alignment errors) = %02x\n",
- BX_NE2K_THIS s.tallycnt_0);
- // fall through into TCR
- case 0x020d:
- dbg_printf ("TCR (Transmit Configuration Register):\n ");
- SHOW_FIELD (TCR, crc_disable);
- SHOW_FIELD (TCR, loop_cntl);
- SHOW_FIELD (TCR, ext_stoptx);
- SHOW_FIELD (TCR, coll_prio);
- SHOW_FIELD (TCR, reserved);
- dbg_printf ("\n");
- break;
- case 0x000e:
- dbg_printf ("CNTR1 = Tally Counter 1 (CRC Errors) = %02x\n",
- BX_NE2K_THIS s.tallycnt_1);
- // fall through into DCR
- case 0x020e:
- dbg_printf ("DCR (Data Configuration Register):\n ");
- SHOW_FIELD (DCR, wdsize);
- SHOW_FIELD (DCR, endian);
- SHOW_FIELD (DCR, longaddr);
- SHOW_FIELD (DCR, loop);
- SHOW_FIELD (DCR, auto_rx);
- SHOW_FIELD (DCR, fifo_size);
- dbg_printf ("\n");
- break;
- case 0x000f:
- dbg_printf ("CNTR2 = Tally Counter 2 (Missed Packet Errors) = %02x\n",
- BX_NE2K_THIS s.tallycnt_2);
- // fall through into IMR
- case 0x020f:
- dbg_printf ("IMR (Interrupt Mask Register)\n ");
- SHOW_FIELD (IMR, rx_inte);
- SHOW_FIELD (IMR, tx_inte);
- SHOW_FIELD (IMR, rxerr_inte);
- SHOW_FIELD (IMR, txerr_inte);
- SHOW_FIELD (IMR, overw_inte);
- SHOW_FIELD (IMR, cofl_inte);
- SHOW_FIELD (IMR, rdma_inte);
- SHOW_FIELD (IMR, reserved);
- dbg_printf ("\n");
- break;
- case 0x0101:
- case 0x0102: BX_DUPLICATE(0x0101);
- case 0x0103: BX_DUPLICATE(0x0101);
- case 0x0104: BX_DUPLICATE(0x0101);
- case 0x0105: BX_DUPLICATE(0x0101);
- case 0x0106: BX_DUPLICATE(0x0101);
- dbg_printf ("MAC address registers are located at page 1, registers 1-6.\n");
- dbg_printf ("The MAC address is ");
- for (i=0; i<=5; i++)
- dbg_printf ("%02x%c", BX_NE2K_THIS s.physaddr[i], i<5?':' : '\n');
- break;
- case 0x0107:
- dbg_printf ("Current page is 0x%02x\n", BX_NE2K_THIS s.curr_page);
- break;
- case 0x0108:
- case 0x0109: BX_DUPLICATE(0x0108);
- case 0x010A: BX_DUPLICATE(0x0108);
- case 0x010B: BX_DUPLICATE(0x0108);
- case 0x010C: BX_DUPLICATE(0x0108);
- case 0x010D: BX_DUPLICATE(0x0108);
- case 0x010E: BX_DUPLICATE(0x0108);
- case 0x010F: BX_DUPLICATE(0x0108);
- dbg_printf ("MAR0-7 (Multicast address registers 0-7) are set to:\n");
- for (i=0; i<8; i++) dbg_printf ("%02x ", BX_NE2K_THIS s.mchash[i]);
- dbg_printf ("\nMAR0 is listed first.\n");
- break;
- case 0x0001:
- case 0x0002: BX_DUPLICATE(0x0001);
- case 0x0201: BX_DUPLICATE(0x0001);
- case 0x0202: BX_DUPLICATE(0x0001);
- dbg_printf ("PSTART = Page start register = %02x\n", BX_NE2K_THIS s.page_start);
- dbg_printf ("PSTOP = Page stop register = %02x\n", BX_NE2K_THIS s.page_stop);
- dbg_printf ("Local DMA address = %02x %02x\n",
- BX_HIGH_BYTE(BX_NE2K_THIS s.local_dma),
- BX_LOW_BYTE(BX_NE2K_THIS s.local_dma));
- break;
- case 0x0203:
- dbg_printf ("Remote Next Packet Pointer = %02x\n", BX_NE2K_THIS s.rempkt_ptr);
- break;
- case 0x0205:
- dbg_printf ("Local Next Packet Pointer = %02x\n", BX_NE2K_THIS s.localpkt_ptr);
- break;
- case 0x0206:
- case 0x0207: BX_DUPLICATE(0x0206);
- dbg_printf ("Address Counter= %02x %02x\n",
- BX_HIGH_BYTE(BX_NE2K_THIS s.address_cnt),
- BX_LOW_BYTE(BX_NE2K_THIS s.address_cnt));
- break;
- case 0x0208:
- case 0x0209: BX_DUPLICATE(0x0208);
- case 0x020A: BX_DUPLICATE(0x0208);
- case 0x020B: BX_DUPLICATE(0x0208);
- if (!brief) dbg_printf ("Reserved\n");
- case 0xffff:
- dbg_printf ("IMR (Interrupt Mask Register):\n ");
- dbg_printf ("\n");
- break;
- default:
- dbg_printf ("NE2K info: sorry, page %d register %d cannot be displayed.\n", page, reg);
- }
- if (!brief)
- dbg_printf ("\n");
-}
-
-#else
-
-void
-bx_ne2k_c::print_info (FILE *fp, int page, int reg, int brief)
-{
-}
-
-#endif
-
-#endif /* if BX_NE2K_SUPPORT */
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: ne2k.h,v 1.11 2003/03/02 23:59:11 cbothamy Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2001 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-// Peter Grehan (grehan@iprg.nokia.com) coded all of this
-// NE2000/ether stuff.
-
-//
-// An implementation of an ne2000 ISA ethernet adapter. This part uses
-// a National Semiconductor DS-8390 ethernet MAC chip, with some h/w
-// to provide a windowed memory region for the chip and a MAC address.
-//
-
-
-#if BX_USE_NE2K_SMF
-# define BX_NE2K_SMF static
-# define BX_NE2K_THIS theNE2kDevice->
-#else
-# define BX_NE2K_SMF
-# define BX_NE2K_THIS this->
-#endif
-
-#define BX_NE2K_MEMSIZ (32*1024)
-#define BX_NE2K_MEMSTART (16*1024)
-#define BX_NE2K_MEMEND (BX_NE2K_MEMSTART + BX_NE2K_MEMSIZ)
-
-typedef struct {
- //
- // ne2k register state
-
- //
- // Page 0
- //
- // Command Register - 00h read/write
- struct {
- bx_bool stop; // STP - Software Reset command
- bx_bool start; // START - start the NIC
- bx_bool tx_packet; // TXP - initiate packet transmission
- Bit8u rdma_cmd; // RD0,RD1,RD2 - Remote DMA command
- Bit8u pgsel; // PS0,PS1 - Page select
- } CR;
- // Interrupt Status Register - 07h read/write
- struct {
- bx_bool pkt_rx; // PRX - packet received with no errors
- bx_bool pkt_tx; // PTX - packet transmitted with no errors
- bx_bool rx_err; // RXE - packet received with 1 or more errors
- bx_bool tx_err; // TXE - packet tx'd " " " " "
- bx_bool overwrite; // OVW - rx buffer resources exhausted
- bx_bool cnt_oflow; // CNT - network tally counter MSB's set
- bx_bool rdma_done; // RDC - remote DMA complete
- bx_bool reset; // RST - reset status
- } ISR;
- // Interrupt Mask Register - 0fh write
- struct {
- bx_bool rx_inte; // PRXE - packet rx interrupt enable
- bx_bool tx_inte; // PTXE - packet tx interrput enable
- bx_bool rxerr_inte; // RXEE - rx error interrupt enable
- bx_bool txerr_inte; // TXEE - tx error interrupt enable
- bx_bool overw_inte; // OVWE - overwrite warn int enable
- bx_bool cofl_inte; // CNTE - counter o'flow int enable
- bx_bool rdma_inte; // RDCE - remote DMA complete int enable
- bx_bool reserved; // D7 - reserved
- } IMR;
- // Data Configuration Register - 0eh write
- struct {
- bx_bool wdsize; // WTS - 8/16-bit select
- bx_bool endian; // BOS - byte-order select
- bx_bool longaddr; // LAS - long-address select
- bx_bool loop; // LS - loopback select
- bx_bool auto_rx; // AR - auto-remove rx packets with remote DMA
- Bit8u fifo_size; // FT0,FT1 - fifo threshold
- } DCR;
- // Transmit Configuration Register - 0dh write
- struct {
- bx_bool crc_disable; // CRC - inhibit tx CRC
- Bit8u loop_cntl; // LB0,LB1 - loopback control
- bx_bool ext_stoptx; // ATD - allow tx disable by external mcast
- bx_bool coll_prio; // OFST - backoff algorithm select
- Bit8u reserved; // D5,D6,D7 - reserved
- } TCR;
- // Transmit Status Register - 04h read
- struct {
- bx_bool tx_ok; // PTX - tx complete without error
- bx_bool reserved; // D1 - reserved
- bx_bool collided; // COL - tx collided >= 1 times
- bx_bool aborted; // ABT - aborted due to excessive collisions
- bx_bool no_carrier; // CRS - carrier-sense lost
- bx_bool fifo_ur; // FU - FIFO underrun
- bx_bool cd_hbeat; // CDH - no tx cd-heartbeat from transceiver
- bx_bool ow_coll; // OWC - out-of-window collision
- } TSR;
- // Receive Configuration Register - 0ch write
- struct {
- bx_bool errors_ok; // SEP - accept pkts with rx errors
- bx_bool runts_ok; // AR - accept < 64-byte runts
- bx_bool broadcast; // AB - accept eth broadcast address
- bx_bool multicast; // AM - check mcast hash array
- bx_bool promisc; // PRO - accept all packets
- bx_bool monitor; // MON - check pkts, but don't rx
- Bit8u reserved; // D6,D7 - reserved
- } RCR;
- // Receive Status Register - 0ch read
- struct {
- bx_bool rx_ok; // PRX - rx complete without error
- bx_bool bad_crc; // CRC - Bad CRC detected
- bx_bool bad_falign; // FAE - frame alignment error
- bx_bool fifo_or; // FO - FIFO overrun
- bx_bool rx_missed; // MPA - missed packet error
- bx_bool rx_mbit; // PHY - unicast or mcast/bcast address match
- bx_bool rx_disabled; // DIS - set when in monitor mode
- bx_bool deferred; // DFR - collision active
- } RSR;
-
- Bit16u local_dma; // 01,02h read ; current local DMA addr
- Bit8u page_start; // 01h write ; page start register
- Bit8u page_stop; // 02h write ; page stop register
- Bit8u bound_ptr; // 03h read/write ; boundary pointer
- Bit8u tx_page_start; // 04h write ; transmit page start register
- Bit8u num_coll; // 05h read ; number-of-collisions register
- Bit16u tx_bytes; // 05,06h write ; transmit byte-count register
- Bit8u fifo; // 06h read ; FIFO
- Bit16u remote_dma; // 08,09h read ; current remote DMA addr
- Bit16u remote_start; // 08,09h write ; remote start address register
- Bit16u remote_bytes; // 0a,0bh write ; remote byte-count register
- Bit8u tallycnt_0; // 0dh read ; tally counter 0 (frame align errors)
- Bit8u tallycnt_1; // 0eh read ; tally counter 1 (CRC errors)
- Bit8u tallycnt_2; // 0fh read ; tally counter 2 (missed pkt errors)
-
- //
- // Page 1
- //
- // Command Register 00h (repeated)
- //
- Bit8u physaddr[6]; // 01-06h read/write ; MAC address
- Bit8u curr_page; // 07h read/write ; current page register
- Bit8u mchash[8]; // 08-0fh read/write ; multicast hash array
-
- //
- // Page 2 - diagnostic use only
- //
- // Command Register 00h (repeated)
- //
- // Page Start Register 01h read (repeated)
- // Page Stop Register 02h read (repeated)
- // Current Local DMA Address 01,02h write (repeated)
- // Transmit Page start address 04h read (repeated)
- // Receive Configuration Register 0ch read (repeated)
- // Transmit Configuration Register 0dh read (repeated)
- // Data Configuration Register 0eh read (repeated)
- // Interrupt Mask Register 0fh read (repeated)
- //
- Bit8u rempkt_ptr; // 03h read/write ; remote next-packet pointer
- Bit8u localpkt_ptr; // 05h read/write ; local next-packet pointer
- Bit16u address_cnt; // 06,07h read/write ; address counter
-
- //
- // Page 3 - should never be modified.
- //
-
- // Novell ASIC state
- Bit8u macaddr[32]; // ASIC ROM'd MAC address, even bytes
- Bit8u mem[BX_NE2K_MEMSIZ]; // on-chip packet memory
-
- // ne2k internal state
- Bit32u base_address;
- int base_irq;
- int tx_timer_index;
- int tx_timer_active;
-
-} bx_ne2k_t;
-
-
-
-class bx_ne2k_c : public bx_ne2k_stub_c {
-public:
- bx_ne2k_c(void);
- ~bx_ne2k_c(void);
- virtual void init(void);
- virtual void reset(unsigned type);
- virtual void print_info (FILE *file, int page, int reg, int nodups);
-
-private:
- bx_ne2k_t s;
-
- eth_pktmover_c *ethdev;
-
- BX_NE2K_SMF Bit32u read_cr(void);
- BX_NE2K_SMF void write_cr(Bit32u value);
-
- BX_NE2K_SMF Bit32u chipmem_read(Bit32u address, unsigned io_len) BX_CPP_AttrRegparmN(2);
- BX_NE2K_SMF Bit32u asic_read(Bit32u offset, unsigned io_len) BX_CPP_AttrRegparmN(2);
- BX_NE2K_SMF Bit32u page0_read(Bit32u offset, unsigned io_len);
- BX_NE2K_SMF Bit32u page1_read(Bit32u offset, unsigned io_len);
- BX_NE2K_SMF Bit32u page2_read(Bit32u offset, unsigned io_len);
- BX_NE2K_SMF Bit32u page3_read(Bit32u offset, unsigned io_len);
-
- BX_NE2K_SMF void chipmem_write(Bit32u address, Bit32u value, unsigned io_len) BX_CPP_AttrRegparmN(3);
- BX_NE2K_SMF void asic_write(Bit32u address, Bit32u value, unsigned io_len);
- BX_NE2K_SMF void page0_write(Bit32u address, Bit32u value, unsigned io_len);
- BX_NE2K_SMF void page1_write(Bit32u address, Bit32u value, unsigned io_len);
- BX_NE2K_SMF void page2_write(Bit32u address, Bit32u value, unsigned io_len);
- BX_NE2K_SMF void page3_write(Bit32u address, Bit32u value, unsigned io_len);
-
- static void tx_timer_handler(void *);
- BX_NE2K_SMF void tx_timer(void);
-
- static void rx_handler(void *arg, const void *buf, unsigned len);
- BX_NE2K_SMF unsigned mcast_index(const void *dst);
- BX_NE2K_SMF void rx_frame(const void *buf, unsigned io_len);
-
- static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len);
- static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len);
-#if !BX_USE_NE2K_SMF
- Bit32u read(Bit32u address, unsigned io_len);
- void write(Bit32u address, Bit32u value, unsigned io_len);
-#endif
-};
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: osdep.cc,v 1.14.2.1 2004/02/06 22:14:34 danielg4 Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2001 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-//
-// osdep.cc
-//
-// Provide definition of library functions that are missing on various
-// systems. The only reason this is a .cc file rather than a .c file
-// is so that it can include bochs.h. Bochs.h includes all the required
-// system headers, with appropriate #ifdefs for different compilers and
-// platforms.
-//
-
-#include "bochs.h"
-
-//////////////////////////////////////////////////////////////////////
-// Missing library functions. These should work on any platform
-// that needs them.
-//////////////////////////////////////////////////////////////////////
-
-#if !BX_HAVE_SNPRINTF
-/* XXX use real snprintf */
-/* if they don't have snprintf, just use sprintf */
-int bx_snprintf (char *s, size_t maxlen, const char *format, ...)
-{
- va_list arg;
- int done;
-
- va_start (arg, format);
- done = vsprintf (s, format, arg);
- va_end (arg);
-
- return done;
-}
-#endif /* !BX_HAVE_SNPRINTF */
-
-
-#if (!BX_HAVE_STRTOULL && !BX_HAVE_STRTOUQ)
-/* taken from glibc-2.2.2: strtod.c, and stripped down a lot. There are
- still a few leftover references to decimal points and exponents,
- but it works for bases 10 and 16 */
-
-#define RETURN(val,end) \
- do { if (endptr != NULL) *endptr = (char *) (end); \
- return val; } while (0)
-
-Bit64u
-bx_strtoull (const char *nptr, char **endptr, int baseignore)
-{
- int negative; /* The sign of the number. */
- int exponent; /* Exponent of the number. */
-
- /* Numbers starting `0X' or `0x' have to be processed with base 16. */
- int base = 10;
-
- /* Number of bits currently in result value. */
- int bits;
-
- /* Running pointer after the last character processed in the string. */
- const char *cp, *tp;
- /* Start of significant part of the number. */
- const char *startp, *start_of_digits;
- /* Total number of digit and number of digits in integer part. */
- int dig_no;
- /* Contains the last character read. */
- char c;
-
- Bit64s n = 0;
- char const *p;
-
- /* Prepare number representation. */
- exponent = 0;
- negative = 0;
- bits = 0;
-
- /* Parse string to get maximal legal prefix. We need the number of
- characters of the integer part, the fractional part and the exponent. */
- cp = nptr - 1;
- /* Ignore leading white space. */
- do
- c = *++cp;
- while (isspace (c));
-
- /* Get sign of the result. */
- if (c == '-')
- {
- negative = 1;
- c = *++cp;
- }
- else if (c == '+')
- c = *++cp;
-
- if (c < '0' || c > '9')
- {
- /* It is really a text we do not recognize. */
- RETURN (0, nptr);
- }
-
- /* First look whether we are faced with a hexadecimal number. */
- if (c == '0' && tolower (cp[1]) == 'x')
- {
- /* Okay, it is a hexa-decimal number. Remember this and skip
- the characters. BTW: hexadecimal numbers must not be
- grouped. */
- base = 16;
- cp += 2;
- c = *cp;
- }
-
- /* Record the start of the digits, in case we will check their grouping. */
- start_of_digits = startp = cp;
-
- /* Ignore leading zeroes. This helps us to avoid useless computations. */
- while (c == '0')
- c = *++cp;
-
- /* If no other digit but a '0' is found the result is 0.0.
- Return current read pointer. */
- if ((c < '0' || c > '9')
- && (base == 16 && (c < tolower ('a') || c > tolower ('f')))
- && (base == 16 && (cp == start_of_digits || tolower (c) != 'p'))
- && (base != 16 && tolower (c) != 'e'))
- {
- tp = start_of_digits;
- /* If TP is at the start of the digits, there was no correctly
- grouped prefix of the string; so no number found. */
- RETURN (0, tp == start_of_digits ? (base == 16 ? cp - 1 : nptr) : tp);
- }
-
- /* Remember first significant digit and read following characters until the
- decimal point, exponent character or any non-FP number character. */
- startp = cp;
- dig_no = 0;
- while (1)
- {
- if ((c >= '0' && c <= '9')
- || (base == 16 && tolower (c) >= 'a' && tolower (c) <= 'f'))
- ++dig_no;
- else
- break;
- c = *++cp;
- }
-
- /* The whole string is parsed. Store the address of the next character. */
- if (endptr)
- *endptr = (char *) cp;
-
- if (dig_no == 0)
- return 0;
-
- for (p=start_of_digits; p!=cp; p++) {
- n = n * (Bit64s)base;
- c = tolower (*p);
- c = (c >= 'a') ? (10+c-'a') : c-'0';
- n = n + (Bit64s)c;
- //printf ("after shifting in digit %c, n is %lld\n", *p, n);
- }
- return negative? -n : n;
-}
-#endif /* !BX_HAVE_STRTOULL */
-
-#if BX_TEST_STRTOULL_MAIN
-/* test driver for strtoull. Do not compile by default. */
-int main (int argc, char **argv)
-{
- char buf[256], *endbuf;
- long l;
- Bit64s ll;
- while (1) {
- printf ("Enter a long int: ");
- gets (buf);
- l = strtoul (buf, &endbuf, 10);
- printf ("As a long, %ld\n", l);
- printf ("Endbuf is at buf[%d]\n", endbuf-buf);
- ll = bx_strtoull (buf, &endbuf, 10);
- printf ("As a long long, %lld\n", ll);
- printf ("Endbuf is at buf[%d]\n", endbuf-buf);
- }
- return 0;
-}
-#endif /* BX_TEST_STRTOULL_MAIN */
-
-#if !BX_HAVE_STRDUP
-/* XXX use real strdup */
-char *bx_strdup(const char *str)
-{
- char *temp;
-
- temp = (char*)malloc(strlen(str)+1);
- sprintf(temp, "%s", str);
- return temp;
-
- // Well, I'm sure this isn't how strdup is REALLY implemented,
- // but it works...
-}
-#endif /* !BX_HAVE_STRDUP */
-
-#if !BX_HAVE_STRREV
-char *bx_strrev(char *str)
-{
- char *p1, *p2;
-
- if (! str || ! *str)
- return str;
-
- for (p1 = str, p2 = str + strlen(str) - 1; p2 > p1; ++p1, --p2) {
- *p1 ^= *p2;
- *p2 ^= *p1;
- *p1 ^= *p2;
- }
- return str;
-}
-#endif /* !BX_HAVE_STRREV */
-
-#if BX_WITH_MACOS
-namespace std{extern "C" {char *mktemp(char *tpl);}}
-#endif
-#if !BX_HAVE_MKSTEMP
-int bx_mkstemp(char *tpl)
-{
- mktemp(tpl);
- return ::open(tpl, O_RDWR | O_CREAT | O_TRUNC
-# ifdef O_BINARY
- | O_BINARY
-# endif
- , S_IWUSR | S_IRUSR | S_IRGRP | S_IWGRP);
-}
-#endif // !BX_HAVE_MKSTEMP
-
-//////////////////////////////////////////////////////////////////////
-// Missing library functions, implemented for MacOS only
-//////////////////////////////////////////////////////////////////////
-
-#if BX_WITH_MACOS
-// these functions are part of MacBochs. They are not intended to be
-// portable!
-#include <Devices.h>
-#include <Files.h>
-#include <Disks.h>
-
-int fd_read(char *buffer, Bit32u offset, Bit32u bytes)
-{
- OSErr err;
- IOParam param;
-
- param.ioRefNum=-5; // Refnum of the floppy disk driver
- param.ioVRefNum=1;
- param.ioPosMode=fsFromStart;
- param.ioPosOffset=offset;
- param.ioBuffer=buffer;
- param.ioReqCount=bytes;
- err = PBReadSync((union ParamBlockRec *)(¶m));
- return param.ioActCount;
-}
-
-int fd_write(char *buffer, Bit32u offset, Bit32u bytes)
-{
- OSErr err;
- IOParam param;
-
- param.ioRefNum=-5; // Refnum of the floppy disk driver
- param.ioVRefNum=1;
- param.ioPosMode=fsFromStart;
- param.ioPosOffset=offset;
- param.ioBuffer=buffer;
- param.ioReqCount=bytes;
- err = PBWriteSync((union ParamBlockRec *)(¶m));
- return param.ioActCount;
-}
-
-int fd_stat(struct stat *buf)
-{
- OSErr err;
- DrvSts status;
- int result;
-
- result = 0;
- err = DriveStatus(1, &status);
- if (status.diskInPlace <1 || status.diskInPlace > 2)
- result = -1;
- buf->st_mode = S_IFCHR;
- return result;
-}
-#endif /* BX_WITH_MACOS */
-
-
-
-//////////////////////////////////////////////////////////////////////
-// New functions to replace library functions
-// with OS-independent versions
-//////////////////////////////////////////////////////////////////////
-
-#if BX_HAVE_REALTIME_USEC
-# if BX_HAVE_GETTIMEOFDAY
-Bit64u bx_get_realtime64_usec (void) {
- timeval thetime;
- gettimeofday(&thetime,0);
- Bit64u mytime;
- mytime=(Bit64u)thetime.tv_sec*(Bit64u)1000000+(Bit64u)thetime.tv_usec;
- return mytime;
-}
-# elif defined(WIN32)
-Bit64u last_realtime64_top = 0;
-Bit64u last_realtime64_bottom = 0;
-Bit64u bx_get_realtime64_usec (void) {
- Bit64u new_bottom = ((Bit64u) GetTickCount()) & BX_CONST64(0x0FFFFFFFF);
- if(new_bottom < last_realtime64_bottom) {
- last_realtime64_top += BX_CONST64(0x0000000100000000);
- }
- last_realtime64_bottom = new_bottom;
- Bit64u interim_realtime64 =
- (last_realtime64_top & BX_CONST64(0xFFFFFFFF00000000)) |
- (new_bottom & BX_CONST64(0x00000000FFFFFFFF));
- return interim_realtime64*(BX_CONST64(1000));
-}
-# endif
-#endif
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: parallel.cc,v 1.24 2003/10/29 17:29:26 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-//
-////////////////////////////////////////////////////////
-// This code was just a few stubs until Volker.Ruppert@t-online.de
-// fixed it up in November 2001.
-
-
-// Define BX_PLUGGABLE in files that can be compiled into plugins. For
-// platforms that require a special tag on exported symbols, BX_PLUGGABLE
-// is used to know when we are exporting symbols and when we are importing.
-#define BX_PLUGGABLE
-
-#include "bochs.h"
-#define LOG_THIS theParallelDevice->
-
-bx_parallel_c *theParallelDevice = NULL;
-
- int
-libparallel_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[])
-{
- theParallelDevice = new bx_parallel_c ();
- bx_devices.pluginParallelDevice = theParallelDevice;
- BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theParallelDevice, BX_PLUGIN_PARALLEL);
- return(0); // Success
-}
-
- void
-libparallel_LTX_plugin_fini(void)
-{
-}
-
-bx_parallel_c::bx_parallel_c(void)
-{
- put("PAR");
- settype(PARLOG);
- s.output = NULL;
-}
-
-bx_parallel_c::~bx_parallel_c(void)
-{
- if (s.output != NULL)
- fclose(s.output);
-}
-
- void
-bx_parallel_c::init(void)
-{
- BX_DEBUG(("Init $Id: parallel.cc,v 1.24 2003/10/29 17:29:26 vruppert Exp $"));
-
- if (bx_options.par[0].Oenabled->get ()) {
-
- /* PARALLEL PORT 1 */
-
- DEV_register_irq(7, "Parallel Port 1");
- BX_INFO (("parallel port 1 at 0x378 irq 7"));
- for (unsigned addr=0x0378; addr<=0x037A; addr++) {
- DEV_register_ioread_handler(this, read_handler, addr, "Parallel Port 1", 1);
- }
- DEV_register_iowrite_handler(this, write_handler, 0x0378, "Parallel Port 1", 1);
- DEV_register_iowrite_handler(this, write_handler, 0x037A, "Parallel Port 1", 1);
-
- BX_PAR_THIS s.STATUS.error = 1;
- BX_PAR_THIS s.STATUS.slct = 1;
- BX_PAR_THIS s.STATUS.pe = 0;
- BX_PAR_THIS s.STATUS.ack = 1;
- BX_PAR_THIS s.STATUS.busy = 1;
-
- BX_PAR_THIS s.CONTROL.strobe = 0;
- BX_PAR_THIS s.CONTROL.autofeed = 0;
- BX_PAR_THIS s.CONTROL.init = 1;
- BX_PAR_THIS s.CONTROL.slct_in = 1;
- BX_PAR_THIS s.CONTROL.irq = 0;
- BX_PAR_THIS s.CONTROL.input = 0;
-
- BX_PAR_THIS s.initmode = 0;
-
- if (strlen(bx_options.par[0].Ooutfile->getptr ()) > 0) {
- s.output = fopen(bx_options.par[0].Ooutfile->getptr (), "wb");
- if (!s.output)
- BX_PANIC (("Could not open '%s' to write parport1 output",
- bx_options.par[0].Ooutfile->getptr ()));
- }
- }
-}
-
- void
-bx_parallel_c::reset(unsigned type)
-{
-}
-
- void
-bx_parallel_c::virtual_printer(void)
-{
- if (BX_PAR_THIS s.STATUS.slct) {
- if (BX_PAR_THIS s.output != NULL) {
- fputc(BX_PAR_THIS s.data, BX_PAR_THIS s.output);
- fflush (BX_PAR_THIS s.output);
- }
- if (BX_PAR_THIS s.CONTROL.irq == 1) {
- DEV_pic_raise_irq(7);
- }
- BX_PAR_THIS s.STATUS.ack = 0;
- BX_PAR_THIS s.STATUS.busy = 1;
- }
- else {
- BX_ERROR(("data is valid, but printer is offline"));
- }
-}
-
- // static IO port read callback handler
- // redirects to non-static class handler to avoid virtual functions
-
- Bit32u
-bx_parallel_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len)
-{
-#if !BX_USE_PAR_SMF
- bx_parallel_c *class_ptr = (bx_parallel_c *) this_ptr;
-
- return( class_ptr->read(address, io_len) );
-}
-
-
- Bit32u
-bx_parallel_c::read(Bit32u address, unsigned io_len)
-{
-#else
- UNUSED(this_ptr);
-#endif // !BX_USE_PAR_SMF
-
- Bit32u retval;
-
- switch (address) {
- /* PARALLEL PORT 1 */
- case 0x0378:
- if (!BX_PAR_THIS s.CONTROL.input) {
- return (Bit32u)BX_PAR_THIS s.data;
- } else {
- BX_ERROR(("read: input mode not supported"));
- return (0xFF);
- }
- break;
- case 0x0379:
- {
- retval = ((BX_PAR_THIS s.STATUS.busy << 7) |
- (BX_PAR_THIS s.STATUS.ack << 6) |
- (BX_PAR_THIS s.STATUS.pe << 5) |
- (BX_PAR_THIS s.STATUS.slct << 4) |
- (BX_PAR_THIS s.STATUS.error << 3));
- if (BX_PAR_THIS s.STATUS.ack == 0) {
- BX_PAR_THIS s.STATUS.ack = 1;
- if (BX_PAR_THIS s.CONTROL.irq == 1) {
- DEV_pic_lower_irq(7);
- }
- }
- if (BX_PAR_THIS s.initmode == 1) {
- BX_PAR_THIS s.STATUS.busy = 1;
- BX_PAR_THIS s.STATUS.slct = 1;
- BX_PAR_THIS s.STATUS.ack = 0;
- if (BX_PAR_THIS s.CONTROL.irq == 1) {
- DEV_pic_raise_irq(7);
- }
- BX_PAR_THIS s.initmode = 0;
- }
- BX_DEBUG(("read: status register returns 0x%02x", retval));
- return retval;
- }
- break;
- case 0x037A:
- {
- retval = ((BX_PAR_THIS s.CONTROL.input << 5) |
- (BX_PAR_THIS s.CONTROL.irq << 4) |
- (BX_PAR_THIS s.CONTROL.slct_in << 3) |
- (BX_PAR_THIS s.CONTROL.init << 2) |
- (BX_PAR_THIS s.CONTROL.autofeed << 1) |
- (BX_PAR_THIS s.CONTROL.strobe));
- BX_DEBUG(("read: control register returns 0x%02x", retval));
- return retval;
- }
- break;
- }
- return(0);
-}
-
-
- // static IO port write callback handler
- // redirects to non-static class handler to avoid virtual functions
-
- void
-bx_parallel_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len)
-{
-#if !BX_USE_PAR_SMF
- bx_parallel_c *class_ptr = (bx_parallel_c *) this_ptr;
-
- class_ptr->write(address, value, io_len);
-}
-
- void
-bx_parallel_c::write(Bit32u address, Bit32u value, unsigned io_len)
-{
-#else
- UNUSED(this_ptr);
-#endif // !BX_USE_PAR_SMF
-
- switch (address) {
- /* PARALLEL PORT 1 */
- case 0x0378:
- BX_PAR_THIS s.data = (Bit8u)value;
- BX_DEBUG(("write: data output register = 0x%02x", (Bit8u)value));
- break;
- case 0x037A:
- {
- if ((value & 0x01) == 0x01) {
- if (BX_PAR_THIS s.CONTROL.strobe == 0) {
- BX_PAR_THIS s.CONTROL.strobe = 1;
- virtual_printer(); // data is valid now
- }
- } else {
- if (BX_PAR_THIS s.CONTROL.strobe == 1) {
- BX_PAR_THIS s.CONTROL.strobe = 0;
- }
- }
- BX_PAR_THIS s.CONTROL.autofeed = ((value & 0x02) == 0x02);
- if ((value & 0x04) == 0x04) {
- if (BX_PAR_THIS s.CONTROL.init == 0) {
- BX_PAR_THIS s.CONTROL.init = 1;
- BX_PAR_THIS s.STATUS.busy = 0;
- BX_PAR_THIS s.STATUS.slct = 0;
- BX_PAR_THIS s.initmode = 1;
- BX_DEBUG(("printer init requested"));
- }
- } else {
- if (BX_PAR_THIS s.CONTROL.init == 1) {
- BX_PAR_THIS s.CONTROL.init = 0;
- }
- }
- if ((value & 0x08) == 0x08) {
- if (BX_PAR_THIS s.CONTROL.slct_in == 0) {
- BX_PAR_THIS s.CONTROL.slct_in = 1;
- BX_DEBUG(("printer now online"));
- }
- } else {
- if (BX_PAR_THIS s.CONTROL.slct_in == 1) {
- BX_PAR_THIS s.CONTROL.slct_in = 0;
- BX_DEBUG(("printer now offline"));
- }
- }
- BX_PAR_THIS s.STATUS.slct = BX_PAR_THIS s.CONTROL.slct_in;
- if ((value & 0x10) == 0x10) {
- if (BX_PAR_THIS s.CONTROL.irq == 0) {
- BX_PAR_THIS s.CONTROL.irq = 1;
- BX_DEBUG(("irq mode selected"));
- }
- } else {
- if (BX_PAR_THIS s.CONTROL.irq == 1) {
- BX_PAR_THIS s.CONTROL.irq = 0;
- BX_DEBUG(("polling mode selected"));
- }
- }
- if ((value & 0x20) == 0x20) {
- if (BX_PAR_THIS s.CONTROL.input == 0) {
- BX_PAR_THIS s.CONTROL.input = 1;
- BX_DEBUG(("data input mode selected"));
- }
- } else {
- if (BX_PAR_THIS s.CONTROL.input == 1) {
- BX_PAR_THIS s.CONTROL.input = 0;
- BX_DEBUG(("data output mode selected"));
- }
- }
- if ((value & 0xC0) > 0) {
- BX_ERROR(("write: unsupported control bit ignored"));
- }
- }
- break;
- }
-}
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: parallel.h,v 1.11 2002/10/25 11:44:40 bdenney Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2001 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-#if BX_USE_PAR_SMF
-# define BX_PAR_SMF static
-# define BX_PAR_THIS theParallelDevice->
-#else
-# define BX_PAR_SMF
-# define BX_PAR_THIS this->
-#endif
-
-typedef struct {
- Bit8u data;
- struct {
- bx_bool error;
- bx_bool slct;
- bx_bool pe;
- bx_bool ack;
- bx_bool busy;
- } STATUS;
- struct {
- bx_bool strobe;
- bx_bool autofeed;
- bx_bool init;
- bx_bool slct_in;
- bx_bool irq;
- bx_bool input;
- } CONTROL;
- FILE *output;
- bx_bool initmode;
-} bx_par_t;
-
-
-
-class bx_parallel_c : public bx_devmodel_c {
-public:
-
- bx_parallel_c(void);
- ~bx_parallel_c(void);
- virtual void init(void);
- virtual void reset(unsigned type);
-
-private:
- bx_par_t s;
-
- static void virtual_printer();
-
- static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len);
- static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len);
-#if !BX_USE_PAR_SMF
- Bit32u read(Bit32u address, unsigned io_len);
- void write(Bit32u address, Bit32u value, unsigned io_len);
-#endif
- };
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: pc_system.cc,v 1.34 2003/06/07 19:16:51 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-
-#include "bochs.h"
-#define LOG_THIS bx_pc_system.
-
-#ifdef WIN32
-#ifndef __MINGW32__
-// #include <winsock2.h> // +++
-#include <winsock.h>
-#endif
-#endif
-
-#if BX_SHOW_IPS
-unsigned long ips_count=0;
-#endif
-
-#if defined(PROVIDE_M_IPS)
-double m_ips; // Millions of Instructions Per Second
-#endif
-
-#ifdef BX_USE_VMX
-unsigned int tsc_per_bx_tick;
-#endif
-
-// Option for turning off BX_TIMER_DEBUG?
-// Check out m_ips and ips
-
-#define SpewPeriodicTimerInfo 0
-#define MinAllowableTimerPeriod 1
-
-
-#if SpewPeriodicTimerInfo
-// If debugging, set the heartbeat to 5M cycles. Each heartbeat
-// spews the active timer info.
-const Bit64u bx_pc_system_c::NullTimerInterval = 5000000;
-#else
-// This must be the maximum 32-bit unsigned int value, NOT (Bit64u) -1.
-const Bit64u bx_pc_system_c::NullTimerInterval = 0xffffffff;
-#endif
-
- // constructor
-bx_pc_system_c::bx_pc_system_c(void)
-{
- this->put("SYS");
-
- // Timer[0] is the null timer. It is initialized as a special
- // case here. It should never be turned off or modified, and its
- // duration should always remain the same.
- ticksTotal = 0; // Reset ticks since emulator started.
- timer[0].period = NullTimerInterval;
- timer[0].timeToFire = ticksTotal + NullTimerInterval;
- timer[0].active = 1;
- timer[0].continuous = 1;
- timer[0].funct = nullTimer;
- timer[0].this_ptr = this;
- currCountdown = NullTimerInterval;
- currCountdownPeriod = NullTimerInterval;
- numTimers = 1; // So far, only the nullTimer.
- lastTimeUsec = 0;
- usecSinceLast = 0;
-}
-
- void
-bx_pc_system_c::init_ips(Bit32u ips)
-{
- HRQ = 0;
-
- enable_a20 = 1;
- //set_INTR (0);
-
-#if BX_CPU_LEVEL < 2
- a20_mask = 0xfffff;
-#elif BX_CPU_LEVEL == 2
- a20_mask = 0xffffff;
-#else /* 386+ */
- a20_mask = 0xffffffff;
-#endif
-
-#ifdef BX_USE_VMX
- Bit64u phy_cpu_freq = cpu_calibrate_ticks();
-
- if (ips == 500000) { //default ips: we use fixed scaling factor to calulate ips
- tsc_per_bx_tick = 2000;
- ips = phy_cpu_freq / tsc_per_bx_tick;
- } else //use uesr defined ips to calulate factor
- tsc_per_bx_tick = ((phy_cpu_freq + (ips>>1)) / ips);
-#endif
-
- // parameter 'ips' is the processor speed in Instructions-Per-Second
- m_ips = double(ips) / 1000000.0L;
-
- BX_DEBUG(("ips = %u", (unsigned) ips));
-}
-
- void
-bx_pc_system_c::set_HRQ(bx_bool val)
-{
- HRQ = val;
- if (val)
- BX_CPU(0)->async_event = 1;
-}
-
-
-#if (BX_NUM_SIMULATORS < 2)
- void
-bx_pc_system_c::set_INTR(bx_bool value)
-{
- if (bx_dbg.interrupts)
- BX_INFO(("pc_system: Setting INTR=%d on bootstrap processor %d", (int)value, BX_BOOTSTRAP_PROCESSOR));
- //INTR = value;
- BX_CPU(BX_BOOTSTRAP_PROCESSOR)->set_INTR(value);
-}
-#endif
-
-//
-// Read from the IO memory address space
-//
-
- Bit32u BX_CPP_AttrRegparmN(2)
-bx_pc_system_c::inp(Bit16u addr, unsigned io_len)
-{
- Bit32u ret;
-
- ret = bx_devices.inp(addr, io_len);
-
- return( ret );
-}
-
-
-//
-// Write to the IO memory address space.
-//
-
- void BX_CPP_AttrRegparmN(3)
-bx_pc_system_c::outp(Bit16u addr, Bit32u value, unsigned io_len)
-{
- bx_devices.outp(addr, value, io_len);
-}
-
- void BX_CPP_AttrRegparmN(1)
-bx_pc_system_c::set_enable_a20(Bit8u value)
-{
-#if BX_CPU_LEVEL < 2
- BX_PANIC(("set_enable_a20() called: 8086 emulation"));
-#else
-
-#if BX_SUPPORT_A20
- unsigned old_enable_a20 = enable_a20;
-
- if (value) {
- enable_a20 = 1;
-#if BX_CPU_LEVEL == 2
- a20_mask = 0xffffff; /* 286: enable all 24 address lines */
-#else /* 386+ */
- a20_mask = 0xffffffff; /* 386: enable all 32 address lines */
-#endif
- }
- else {
- enable_a20 = 0;
- a20_mask = 0xffefffff; /* mask off A20 address line */
- }
-
- BX_DBG_A20_REPORT(value);
-
- BX_DEBUG(("A20: set() = %u", (unsigned) enable_a20));
-
- // If there has been a transition, we need to notify the CPUs so
- // they can potentially invalidate certain cache info based on
- // A20-line-applied physical addresses.
- if (old_enable_a20 != enable_a20) {
- for (unsigned i=0; i<BX_SMP_PROCESSORS; i++)
- BX_CPU(i)->pagingA20Changed();
- }
-#else
- BX_DEBUG(("set_enable_a20: ignoring: SUPPORT_A20 = 0"));
-#endif // #if BX_SUPPORT_A20
-
-#endif
-}
-
- bx_bool
-bx_pc_system_c::get_enable_a20(void)
-{
-#if BX_SUPPORT_A20
- if (bx_dbg.a20)
- BX_INFO(("A20: get() = %u", (unsigned) enable_a20));
-
- if (enable_a20) return(1);
- else return(0);
-#else
- BX_INFO(("get_enable_a20: ignoring: SUPPORT_A20 = 0"));
- return(1);
-#endif // #if BX_SUPPORT_A20
-}
-
- int
-bx_pc_system_c::ResetSignal( PCS_OP operation )
-{
- UNUSED( operation );
- // Reset the processor.
-
- BX_ERROR(( "# bx_pc_system_c::ResetSignal() called" ));
- for (int i=0; i<BX_SMP_PROCESSORS; i++)
- BX_CPU(i)->reset(BX_RESET_SOFTWARE);
- DEV_reset_devices(BX_RESET_SOFTWARE);
- return(0);
-}
-
-
- Bit8u
-bx_pc_system_c::IAC(void)
-{
- return( DEV_pic_iac() );
-}
-
- void
-bx_pc_system_c::exit(void)
-{
- if (DEV_hd_present())
- DEV_hd_close_harddrive();
-
- BX_INFO(("Last time is %u", (unsigned) DEV_cmos_get_timeval()));
-
- if (bx_gui) bx_gui->exit();
-}
-
-
-// ================================================
-// Bochs internal timer delivery framework features
-// ================================================
-
- int
-bx_pc_system_c::register_timer( void *this_ptr, void (*funct)(void *),
- Bit32u useconds, bx_bool continuous, bx_bool active, const char *id)
-{
- Bit64u ticks;
-
- // Convert useconds to number of ticks.
- ticks = (Bit64u) (double(useconds) * m_ips);
-
- return register_timer_ticks(this_ptr, funct, ticks, continuous, active, id);
-}
-
- int
-bx_pc_system_c::register_timer_ticks(void* this_ptr, bx_timer_handler_t funct,
- Bit64u ticks, bx_bool continuous, bx_bool active, const char *id)
-{
- unsigned i;
-
-#if BX_TIMER_DEBUG
- if (numTimers >= BX_MAX_TIMERS) {
- BX_PANIC(("register_timer: too many registered timers."));
- }
- if (this_ptr == NULL)
- BX_PANIC(("register_timer_ticks: this_ptr is NULL"));
- if (funct == NULL)
- BX_PANIC(("register_timer_ticks: funct is NULL"));
-#endif
-
- // If the timer frequency is rediculously low, make it more sane.
- // This happens when 'ips' is too low.
- if (ticks < MinAllowableTimerPeriod) {
- //BX_INFO(("register_timer_ticks: adjusting ticks of %llu to min of %u",
- // ticks, MinAllowableTimerPeriod));
- ticks = MinAllowableTimerPeriod;
- }
-
- for (i=0; i < numTimers; i++) {
- if (timer[i].inUse == 0)
- break;
- }
-
- timer[i].inUse = 1;
- timer[i].period = ticks;
- timer[i].timeToFire = (ticksTotal + Bit64u(currCountdownPeriod-currCountdown)) +
- ticks;
- timer[i].active = active;
- timer[i].continuous = continuous;
- timer[i].funct = funct;
- timer[i].this_ptr = this_ptr;
- strncpy(timer[i].id, id, BxMaxTimerIDLen);
- timer[i].id[BxMaxTimerIDLen-1] = 0; // Null terminate if not already.
-
- if (active) {
- if (ticks < Bit64u(currCountdown)) {
- // This new timer needs to fire before the current countdown.
- // Skew the current countdown and countdown period to be smaller
- // by the delta.
- currCountdownPeriod -= (currCountdown - Bit32u(ticks));
- currCountdown = Bit32u(ticks);
- }
- }
-
- // If we didn't find a free slot, increment the bound, numTimers.
- if (i==numTimers)
- numTimers++; // One new timer installed.
-
- // Return timer id.
- return(i);
-}
-
-
- void
-bx_pc_system_c::countdownEvent(void)
-{
- unsigned i;
- Bit64u minTimeToFire;
- bx_bool triggered[BX_MAX_TIMERS];
-
- // The countdown decremented to 0. We need to service all the active
- // timers, and invoke callbacks from those timers which have fired.
-#if BX_TIMER_DEBUG
- if (currCountdown != 0)
- BX_PANIC(("countdownEvent: ticks!=0"));
-#endif
-
- // Increment global ticks counter by number of ticks which have
- // elapsed since the last update.
- ticksTotal += Bit64u(currCountdownPeriod);
- minTimeToFire = (Bit64u) -1;
-
- for (i=0; i < numTimers; i++) {
- triggered[i] = 0; // Reset triggered flag.
- if (timer[i].active) {
-#if BX_TIMER_DEBUG
- if (ticksTotal > timer[i].timeToFire)
- BX_PANIC(("countdownEvent: ticksTotal > timeToFire[%u], D " FMT_LL "u", i,
- timer[i].timeToFire-ticksTotal));
-#endif
- if (ticksTotal == timer[i].timeToFire) {
- // This timer is ready to fire.
- triggered[i] = 1;
-
- if (timer[i].continuous==0) {
- // If triggered timer is one-shot, deactive.
- timer[i].active = 0;
- }
- else {
- // Continuous timer, increment time-to-fire by period.
- timer[i].timeToFire += timer[i].period;
- if (timer[i].timeToFire < minTimeToFire)
- minTimeToFire = timer[i].timeToFire;
- }
- }
- else {
- // This timer is not ready to fire yet.
- if (timer[i].timeToFire < minTimeToFire)
- minTimeToFire = timer[i].timeToFire;
- }
- }
- }
-
- // Calculate next countdown period. We need to do this before calling
- // any of the callbacks, as they may call timer features, which need
- // to be advanced to the next countdown cycle.
- currCountdown = currCountdownPeriod =
- Bit32u(minTimeToFire - ticksTotal);
-
- for (i=0; i < numTimers; i++) {
- // Call requested timer function. It may request a different
- // timer period or deactivate etc.
- if (triggered[i]) {
- timer[i].funct(timer[i].this_ptr);
- }
- }
-}
-
- void
-bx_pc_system_c::nullTimer(void* this_ptr)
-{
- // This function is always inserted in timer[0]. It is sort of
- // a heartbeat timer. It ensures that at least one timer is
- // always active to make the timer logic more simple, and has
- // a duration of less than the maximum 32-bit integer, so that
- // a 32-bit size can be used for the hot countdown timer. The
- // rest of the timer info can be 64-bits. This is also a good
- // place for some logic to report actual emulated
- // instructions-per-second (IPS) data when measured relative to
- // the host computer's wall clock.
-
- UNUSED(this_ptr);
-
-#if SpewPeriodicTimerInfo
- BX_INFO(("==================================="));
- for (unsigned i=0; i < bx_pc_system.numTimers; i++) {
- if (bx_pc_system.timer[i].active) {
- BX_INFO(("BxTimer(%s): period=" FMT_LL "u, continuous=%u",
- bx_pc_system.timer[i].id, bx_pc_system.timer[i].period,
- bx_pc_system.timer[i].continuous));
- }
- }
-#endif
-}
-
-#if BX_DEBUGGER
- void
-bx_pc_system_c::timebp_handler(void* this_ptr)
-{
- BX_CPU(0)->break_point = BREAK_POINT_TIME;
- BX_DEBUG(( "Time breakpoint triggered" ));
-
- if (timebp_queue_size > 1) {
- Bit64s new_diff = timebp_queue[1] - bx_pc_system.time_ticks();
- bx_pc_system.activate_timer_ticks(timebp_timer, new_diff, 1);
- }
- timebp_queue_size--;
- for (int i = 0; i < timebp_queue_size; i++)
- timebp_queue[i] = timebp_queue[i+1];
-}
-#endif // BX_DEBUGGER
-
- Bit64u
-bx_pc_system_c::time_usec_sequential() {
- Bit64u this_time_usec = time_usec();
- if(this_time_usec != lastTimeUsec) {
- Bit64u diff_usec = this_time_usec-lastTimeUsec;
- lastTimeUsec = this_time_usec;
- if(diff_usec >= usecSinceLast) {
- usecSinceLast = 0;
- } else {
- usecSinceLast -= diff_usec;
- }
- }
- usecSinceLast++;
- return (this_time_usec+usecSinceLast);
-}
- Bit64u
-bx_pc_system_c::time_usec() {
- return (Bit64u) (((double)(Bit64s)time_ticks()) / m_ips );
-}
-
- void
-bx_pc_system_c::start_timers(void)
-{
-}
-
- void
-bx_pc_system_c::activate_timer_ticks(unsigned i, Bit64u ticks, bx_bool continuous)
-{
-#if BX_TIMER_DEBUG
- if (i >= numTimers)
- BX_PANIC(("activate_timer_ticks: timer %u OOB", i));
- if (timer[i].period < MinAllowableTimerPeriod)
- BX_PANIC(("activate_timer_ticks: timer[%u].period of " FMT_LL "u < min of %u",
- i, timer[i].period, MinAllowableTimerPeriod));
-#endif
-
- // If the timer frequency is rediculously low, make it more sane.
- // This happens when 'ips' is too low.
- if (ticks < MinAllowableTimerPeriod) {
- //BX_INFO(("activate_timer_ticks: adjusting ticks of %llu to min of %u",
- // ticks, MinAllowableTimerPeriod));
- ticks = MinAllowableTimerPeriod;
- }
-
- timer[i].period = ticks;
- timer[i].timeToFire = (ticksTotal + Bit64u(currCountdownPeriod-currCountdown)) +
- ticks;
- timer[i].active = 1;
- timer[i].continuous = continuous;
-
- if (ticks < Bit64u(currCountdown)) {
- // This new timer needs to fire before the current countdown.
- // Skew the current countdown and countdown period to be smaller
- // by the delta.
- currCountdownPeriod -= (currCountdown - Bit32u(ticks));
- currCountdown = Bit32u(ticks);
- }
-}
-
- void
-bx_pc_system_c::activate_timer(unsigned i, Bit32u useconds, bx_bool continuous)
-{
- Bit64u ticks;
-
-#if BX_TIMER_DEBUG
- if (i >= numTimers)
- BX_PANIC(("activate_timer: timer %u OOB", i));
-#endif
-
- // if useconds = 0, use default stored in period field
- // else set new period from useconds
- if (useconds==0) {
- ticks = timer[i].period;
- }
- else {
- // convert useconds to number of ticks
- ticks = (Bit64u) (double(useconds) * m_ips);
-
- // If the timer frequency is rediculously low, make it more sane.
- // This happens when 'ips' is too low.
- if (ticks < MinAllowableTimerPeriod) {
- //BX_INFO(("activate_timer: adjusting ticks of %llu to min of %u",
- // ticks, MinAllowableTimerPeriod));
- ticks = MinAllowableTimerPeriod;
- }
-
- timer[i].period = ticks;
- }
-
- activate_timer_ticks(i, ticks, continuous);
-}
-
- void
-bx_pc_system_c::deactivate_timer( unsigned i )
-{
-#if BX_TIMER_DEBUG
- if (i >= numTimers)
- BX_PANIC(("deactivate_timer: timer %u OOB", i));
-#endif
-
- timer[i].active = 0;
-}
-
- unsigned
-bx_pc_system_c::unregisterTimer(int timerIndex)
-{
- unsigned i = (unsigned) timerIndex;
-
-#if BX_TIMER_DEBUG
- if (i >= numTimers)
- BX_PANIC(("unregisterTimer: timer %u OOB", i));
- if (i == 0)
- BX_PANIC(("unregisterTimer: timer 0 is the nullTimer!"));
- if (timer[i].inUse == 0)
- BX_PANIC(("unregisterTimer: timer %u is not in-use!", i));
-#endif
-
- if (timer[i].active) {
- BX_PANIC(("unregisterTimer: timer '%s' is still active!", timer[i].id));
- return(0); // Fail.
- }
-
- // Reset timer fields for good measure.
- timer[i].inUse = 0; // No longer registered.
- timer[i].period = BX_MAX_BIT64S; // Max value (invalid)
- timer[i].timeToFire = BX_MAX_BIT64S; // Max value (invalid)
- timer[i].continuous = 0;
- timer[i].funct = NULL;
- timer[i].this_ptr = NULL;
- memset(timer[i].id, 0, BxMaxTimerIDLen);
-
- return(1); // OK
-}
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: pci.cc,v 1.29 2003/07/31 19:51:42 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-//
-// i440FX Support - PMC/DBX
-//
-
-// Define BX_PLUGGABLE in files that can be compiled into plugins. For
-// platforms that require a special tag on exported symbols, BX_PLUGGABLE
-// is used to know when we are exporting symbols and when we are importing.
-#define BX_PLUGGABLE
-
-#include "bochs.h"
-#if BX_PCI_SUPPORT
-
-#define LOG_THIS thePciBridge->
-
-bx_pci_c *thePciBridge = NULL;
-
- int
-libpci_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[])
-{
- thePciBridge = new bx_pci_c ();
- bx_devices.pluginPciBridge = thePciBridge;
- BX_REGISTER_DEVICE_DEVMODEL(plugin, type, thePciBridge, BX_PLUGIN_PCI);
- return(0); // Success
-}
-
- void
-libpci_LTX_plugin_fini(void)
-{
-}
-
-bx_pci_c::bx_pci_c(void)
-{
- put("PCI");
- settype(PCILOG);
-}
-
-bx_pci_c::~bx_pci_c(void)
-{
- // nothing for now
- BX_DEBUG(("Exit."));
-}
-
-
- void
-bx_pci_c::init(void)
-{
- // called once when bochs initializes
- unsigned i;
- BX_PCI_THIS num_pci_handles = 0;
-
- /* set unused elements to appropriate values */
- for (i=0; i < BX_MAX_PCI_DEVICES; i++) {
- BX_PCI_THIS pci_handler[i].read = NULL;
- BX_PCI_THIS pci_handler[i].write = NULL;
- }
-
- for (i=0; i < 0x100; i++) {
- BX_PCI_THIS pci_handler_id[i] = BX_MAX_PCI_DEVICES; // not assigned
- }
-
- // confAddr accepts dword i/o only
- DEV_register_ioread_handler(this, read_handler, 0x0CF8, "i440FX", 4);
- DEV_register_iowrite_handler(this, write_handler, 0x0CF8, "i440FX", 4);
-
- for (i=0x0CFC; i<=0x0CFF; i++) {
- DEV_register_ioread_handler(this, read_handler, i, "i440FX", 7);
- }
- for (i=0x0CFC; i<=0x0CFF; i++) {
- DEV_register_iowrite_handler(this, write_handler, i, "i440FX", 7);
- }
-
- DEV_register_pci_handlers(this, pci_read_handler, pci_write_handler,
- BX_PCI_DEVICE(0,0), "440FX Host bridge");
-
- for (i=0; i<256; i++)
- BX_PCI_THIS s.i440fx.pci_conf[i] = 0x0;
- // readonly registers
- BX_PCI_THIS s.i440fx.pci_conf[0x00] = 0x86;
- BX_PCI_THIS s.i440fx.pci_conf[0x01] = 0x80;
- BX_PCI_THIS s.i440fx.pci_conf[0x02] = 0x37;
- BX_PCI_THIS s.i440fx.pci_conf[0x03] = 0x12;
- BX_PCI_THIS s.i440fx.pci_conf[0x0b] = 0x06;
-}
-
- void
-bx_pci_c::reset(unsigned type)
-{
- BX_PCI_THIS s.i440fx.confAddr = 0;
- BX_PCI_THIS s.i440fx.confData = 0;
-
- BX_PCI_THIS s.i440fx.pci_conf[0x04] = 0x06;
- BX_PCI_THIS s.i440fx.pci_conf[0x05] = 0x00;
- BX_PCI_THIS s.i440fx.pci_conf[0x06] = 0x80;
- BX_PCI_THIS s.i440fx.pci_conf[0x07] = 0x02;
- BX_PCI_THIS s.i440fx.pci_conf[0x0d] = 0x00;
- BX_PCI_THIS s.i440fx.pci_conf[0x0f] = 0x00;
- BX_PCI_THIS s.i440fx.pci_conf[0x50] = 0x00;
- BX_PCI_THIS s.i440fx.pci_conf[0x51] = 0x01;
- BX_PCI_THIS s.i440fx.pci_conf[0x52] = 0x00;
- BX_PCI_THIS s.i440fx.pci_conf[0x53] = 0x80;
- BX_PCI_THIS s.i440fx.pci_conf[0x54] = 0x00;
- BX_PCI_THIS s.i440fx.pci_conf[0x55] = 0x00;
- BX_PCI_THIS s.i440fx.pci_conf[0x56] = 0x00;
- BX_PCI_THIS s.i440fx.pci_conf[0x57] = 0x01;
- BX_PCI_THIS s.i440fx.pci_conf[0x58] = 0x10;
- for (unsigned i=0x59; i<0x60; i++)
- BX_PCI_THIS s.i440fx.pci_conf[i] = 0x00;
-}
-
-
-
- // static IO port read callback handler
- // redirects to non-static class handler to avoid virtual functions
-
- Bit32u
-bx_pci_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len)
-{
-#if !BX_USE_PCI_SMF
- bx_pci_c *class_ptr = (bx_pci_c *) this_ptr;
-
- return( class_ptr->read(address, io_len) );
-}
-
-
- Bit32u
-bx_pci_c::read(Bit32u address, unsigned io_len)
-{
-#else
- UNUSED(this_ptr);
-#endif // !BX_USE_PCI_SMF
-
- switch (address) {
- case 0x0CF8:
- {
- return BX_PCI_THIS s.i440fx.confAddr;
- }
- break;
- case 0x0CFC:
- case 0x0CFD:
- case 0x0CFE:
- case 0x0CFF:
- {
- Bit32u handle, retval;
- Bit8u devfunc, regnum;
-
- if ((BX_PCI_THIS s.i440fx.confAddr & 0x80FF0000) == 0x80000000) {
- devfunc = (BX_PCI_THIS s.i440fx.confAddr >> 8) & 0xff;
- regnum = (BX_PCI_THIS s.i440fx.confAddr & 0xfc) + (address & 0x03);
- handle = BX_PCI_THIS pci_handler_id[devfunc];
- if ((io_len <= 4) && (handle < BX_MAX_PCI_DEVICES))
- retval = (* BX_PCI_THIS pci_handler[handle].read)
- (BX_PCI_THIS pci_handler[handle].this_ptr, regnum, io_len);
- else
- retval = 0xFFFFFFFF;
- }
- else
- retval = 0xFFFFFFFF;
- BX_PCI_THIS s.i440fx.confData = retval;
- return retval;
- }
- }
-
- BX_PANIC(("unsupported IO read to port 0x%x",
- (unsigned) address));
- return(0xffffffff);
-}
-
-
- // static IO port write callback handler
- // redirects to non-static class handler to avoid virtual functions
-
- void
-bx_pci_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len)
-{
-#if !BX_USE_PCI_SMF
- bx_pci_c *class_ptr = (bx_pci_c *) this_ptr;
-
- class_ptr->write(address, value, io_len);
-}
-
- void
-bx_pci_c::write(Bit32u address, Bit32u value, unsigned io_len)
-{
-#else
- UNUSED(this_ptr);
-#endif // !BX_USE_PCI_SMF
-
- switch (address) {
- case 0xCF8:
- {
- BX_PCI_THIS s.i440fx.confAddr = value;
- if ((value & 0x80FFFF00) == 0x80000000) {
- BX_DEBUG(("440FX PMC register 0x%02x selected", value & 0xfc));
- } else if ((value & 0x80000000) == 0x80000000) {
- BX_DEBUG(("440FX request for bus 0x%02x device 0x%02x function 0x%02x",
- (value >> 16) & 0xFF, (value >> 11) & 0x1F, (value >> 8) & 0x07));
- }
- }
- break;
-
- case 0xCFC:
- case 0xCFD:
- case 0xCFE:
- case 0xCFF:
- {
- Bit32u handle;
- Bit8u devfunc, regnum;
-
- if ((BX_PCI_THIS s.i440fx.confAddr & 0x80FF0000) == 0x80000000) {
- devfunc = (BX_PCI_THIS s.i440fx.confAddr >> 8) & 0xff;
- regnum = (BX_PCI_THIS s.i440fx.confAddr & 0xfc) + (address & 0x03);
- handle = BX_PCI_THIS pci_handler_id[devfunc];
- if ((io_len <= 4) && (handle < BX_MAX_PCI_DEVICES)) {
- if (((regnum>=4) && (regnum<=7)) || (regnum==12) || (regnum==13) || (regnum>14)) {
- (* BX_PCI_THIS pci_handler[handle].write)
- (BX_PCI_THIS pci_handler[handle].this_ptr, regnum, value, io_len);
- BX_PCI_THIS s.i440fx.confData = value << (8 * (address & 0x03));
- }
- else
- BX_DEBUG(("read only register, write ignored"));
- }
- }
- }
- break;
-
- default:
- BX_PANIC(("IO write to port 0x%x", (unsigned) address));
- }
-}
-
-
- // static pci configuration space read callback handler
- // redirects to non-static class handler to avoid virtual functions
-
- Bit32u
-bx_pci_c::pci_read_handler(void *this_ptr, Bit8u address, unsigned io_len)
-{
-#if !BX_USE_PCI_SMF
- bx_pci_c *class_ptr = (bx_pci_c *) this_ptr;
-
- return( class_ptr->pci_read(address, io_len) );
-}
-
-
- Bit32u
-bx_pci_c::pci_read(Bit8u address, unsigned io_len)
-{
-#else
- UNUSED(this_ptr);
-#endif // !BX_USE_PCI_SMF
-
- Bit32u val440fx = 0;
-
- if (io_len <= 4) {
- for (unsigned i=0; i<io_len; i++) {
- val440fx |= (BX_PCI_THIS s.i440fx.pci_conf[address+i] << (i*8));
- }
- BX_DEBUG(("440FX PMC read register 0x%02x value 0x%08x", address, val440fx));
- return val440fx;
- }
- else
- return(0xffffffff);
-}
-
-
- // static pci configuration space write callback handler
- // redirects to non-static class handler to avoid virtual functions
-
- void
-bx_pci_c::pci_write_handler(void *this_ptr, Bit8u address, Bit32u value, unsigned io_len)
-{
-#if !BX_USE_PCI_SMF
- bx_pci_c *class_ptr = (bx_pci_c *) this_ptr;
-
- class_ptr->pci_write(address, value, io_len);
-}
-
- void
-bx_pci_c::pci_write(Bit8u address, Bit32u value, unsigned io_len)
-{
-#else
- UNUSED(this_ptr);
-#endif // !BX_USE_PCI_SMF
-
- Bit8u value8;
-
- if (io_len <= 4) {
- for (unsigned i=0; i<io_len; i++) {
- value8 = (value >> (i*8)) & 0xFF;
- switch (address+i) {
- case 0x06:
- case 0x0c:
- break;
- default:
- BX_PCI_THIS s.i440fx.pci_conf[address+i] = value8;
- BX_DEBUG(("440FX PMC write register 0x%02x value 0x%02x", address,
- value8));
- }
- }
- }
-}
-
-
- Bit8u
-bx_pci_c::rd_memType (Bit32u addr)
-{
- switch ((addr & 0xFC000) >> 12) {
- case 0xC0:
- return (BX_PCI_THIS s.i440fx.pci_conf[0x5A] & 0x1);
- case 0xC4:
- return ( (BX_PCI_THIS s.i440fx.pci_conf[0x5A] >> 4) & 0x1);
- case 0xC8:
- return (BX_PCI_THIS s.i440fx.pci_conf[0x5B] & 0x1);
- case 0xCC:
- return ( (BX_PCI_THIS s.i440fx.pci_conf[0x5B] >> 4) & 0x1);
-
-
- case 0xD0:
- return (BX_PCI_THIS s.i440fx.pci_conf[0x5C] & 0x1);
- case 0xD4:
- return ( (BX_PCI_THIS s.i440fx.pci_conf[0x5C] >> 4) & 0x1);
- case 0xD8:
- return (BX_PCI_THIS s.i440fx.pci_conf[0x5D] & 0x1);
- case 0xDC:
- return ( (BX_PCI_THIS s.i440fx.pci_conf[0x5D] >> 4) & 0x1);
-
- case 0xE0:
- return (BX_PCI_THIS s.i440fx.pci_conf[0x5E] & 0x1);
- case 0xE4:
- return ( (BX_PCI_THIS s.i440fx.pci_conf[0x5E] >> 4) & 0x1);
- case 0xE8:
- return (BX_PCI_THIS s.i440fx.pci_conf[0x5F] & 0x1);
- case 0xEC:
- return ( (BX_PCI_THIS s.i440fx.pci_conf[0x5F] >> 4) & 0x1);
-
- case 0xF0:
- case 0xF4:
- case 0xF8:
- case 0xFC:
- return ( (BX_PCI_THIS s.i440fx.pci_conf[0x59] >> 4) & 0x1);
-
- default:
- BX_PANIC(("rd_memType () Error: Memory Type not known !"));
- return(0); // keep compiler happy
- break;
- }
-
-}
-
- Bit8u
-bx_pci_c::wr_memType (Bit32u addr)
-{
- switch ((addr & 0xFC000) >> 12) {
- case 0xC0:
- return ( (BX_PCI_THIS s.i440fx.pci_conf[0x5A] >> 1) & 0x1);
- case 0xC4:
- return ( (BX_PCI_THIS s.i440fx.pci_conf[0x5A] >> 5) & 0x1);
- case 0xC8:
- return ( (BX_PCI_THIS s.i440fx.pci_conf[0x5B] >> 1) & 0x1);
- case 0xCC:
- return ( (BX_PCI_THIS s.i440fx.pci_conf[0x5B] >> 5) & 0x1);
-
-
- case 0xD0:
- return ( (BX_PCI_THIS s.i440fx.pci_conf[0x5C] >> 1) & 0x1);
- case 0xD4:
- return ( (BX_PCI_THIS s.i440fx.pci_conf[0x5C] >> 5) & 0x1);
- case 0xD8:
- return ( (BX_PCI_THIS s.i440fx.pci_conf[0x5D] >> 1) & 0x1);
- case 0xDC:
- return ( (BX_PCI_THIS s.i440fx.pci_conf[0x5D] >> 5) & 0x1);
-
- case 0xE0:
- return ( (BX_PCI_THIS s.i440fx.pci_conf[0x5E] >> 1) & 0x1);
- case 0xE4:
- return ( (BX_PCI_THIS s.i440fx.pci_conf[0x5E] >> 5) & 0x1);
- case 0xE8:
- return ( (BX_PCI_THIS s.i440fx.pci_conf[0x5F] >> 1) & 0x1);
- case 0xEC:
- return ( (BX_PCI_THIS s.i440fx.pci_conf[0x5F] >> 5) & 0x1);
-
- case 0xF0:
- case 0xF4:
- case 0xF8:
- case 0xFC:
- return ( (BX_PCI_THIS s.i440fx.pci_conf[0x59] >> 5) & 0x1);
-
- default:
- BX_PANIC(("wr_memType () Error: Memory Type not known !"));
- return(0); // keep compiler happy
- break;
- }
-}
-
- void
-bx_pci_c::print_i440fx_state()
-{
- int i;
-
- BX_DEBUG(( "i440fxConfAddr:0x%08x", BX_PCI_THIS s.i440fx.confAddr ));
- BX_DEBUG(( "i440fxConfData:0x%08x", BX_PCI_THIS s.i440fx.confData ));
-
-#ifdef DUMP_FULL_I440FX
- for (i=0; i<256; i++) {
- BX_DEBUG(( "i440fxArray%02x:0x%02x", i, BX_PCI_THIS s.i440fx.pci_conf[i] ));
- }
-#else /* DUMP_FULL_I440FX */
- for (i=0x59; i<0x60; i++) {
- BX_DEBUG(( "i440fxArray%02x:0x%02x", i, BX_PCI_THIS s.i440fx.pci_conf[i] ));
- }
-#endif /* DUMP_FULL_I440FX */
-}
-
- bx_bool
-bx_pci_c::register_pci_handlers( void *this_ptr, bx_pci_read_handler_t f1,
- bx_pci_write_handler_t f2, Bit8u devfunc,
- const char *name)
-{
- unsigned handle;
-
- /* first check if device/function is available */
- if (BX_PCI_THIS pci_handler_id[devfunc] == BX_MAX_PCI_DEVICES) {
- if (BX_PCI_THIS num_pci_handles >= BX_MAX_PCI_DEVICES) {
- BX_INFO(("too many PCI devices installed."));
- BX_PANIC((" try increasing BX_MAX_PCI_DEVICES"));
- return false;
- }
- handle = BX_PCI_THIS num_pci_handles++;
- BX_PCI_THIS pci_handler[handle].read = f1;
- BX_PCI_THIS pci_handler[handle].write = f2;
- BX_PCI_THIS pci_handler[handle].this_ptr = this_ptr;
- BX_PCI_THIS pci_handler_id[devfunc] = handle;
- BX_INFO(("%s present at device %d, function %d", name, devfunc >> 3,
- devfunc & 0x07));
- return true; // device/function mapped successfully
- }
- else {
- return false; // device/function not available, return false.
- }
-}
-#endif /* BX_PCI_SUPPORT */
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: pci.h,v 1.14 2003/01/23 19:31:27 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-#define BX_MAX_PCI_DEVICES 20
-
-#define BX_PCI_DEVICE(device, function) ((device)<<3 | (function))
-
-typedef Bit32u (*bx_pci_read_handler_t)(void *, Bit8u, unsigned);
-typedef void (*bx_pci_write_handler_t)(void *, Bit8u, Bit32u, unsigned);
-
-#if BX_USE_PCI_SMF
-# define BX_PCI_SMF static
-# define BX_PCI_THIS thePciBridge->
-#else
-# define BX_PCI_SMF
-# define BX_PCI_THIS this->
-#endif
-
-
-typedef struct {
- Bit32u confAddr;
- Bit32u confData;
- Bit8u pci_conf[256];
- } bx_def440fx_t;
-
-
-
-class bx_pci_c : public bx_pci_stub_c {
-
-public:
- bx_pci_c(void);
- ~bx_pci_c(void);
- virtual void init(void);
- virtual void reset(unsigned type);
- virtual bx_bool register_pci_handlers(void *this_ptr,
- bx_pci_read_handler_t f1,
- bx_pci_write_handler_t f2,
- Bit8u devfunc, const char *name);
- virtual void print_i440fx_state(void);
- virtual Bit8u rd_memType (Bit32u addr);
- virtual Bit8u wr_memType (Bit32u addr);
-
-private:
- Bit8u pci_handler_id[0x100]; // 256 devices/functions
- struct {
- bx_pci_read_handler_t read;
- bx_pci_write_handler_t write;
- void *this_ptr;
- } pci_handler[BX_MAX_PCI_DEVICES];
- unsigned num_pci_handles;
-
- struct {
- bx_def440fx_t i440fx;
- } s;
-
- static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len);
- static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len);
- static Bit32u pci_read_handler(void *this_ptr, Bit8u address, unsigned io_len);
- static void pci_write_handler(void *this_ptr, Bit8u address, Bit32u value, unsigned io_len);
-#if !BX_USE_PCI_SMF
- Bit32u read(Bit32u address, unsigned io_len);
- void write(Bit32u address, Bit32u value, unsigned io_len);
- Bit32u pci_read(Bit8u address, unsigned io_len);
- void pci_write(Bit8u address, Bit32u value, unsigned io_len);
-#endif
- };
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: pci2isa.cc,v 1.10 2003/07/31 19:51:42 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-//
-// i440FX Support - PCI-to-ISA bridge (PIIX3)
-//
-
-// Define BX_PLUGGABLE in files that can be compiled into plugins. For
-// platforms that require a special tag on exported symbols, BX_PLUGGABLE
-// is used to know when we are exporting symbols and when we are importing.
-#define BX_PLUGGABLE
-
-#include "bochs.h"
-#if BX_PCI_SUPPORT
-
-#define LOG_THIS thePci2IsaBridge->
-
-bx_pci2isa_c *thePci2IsaBridge = NULL;
-
- int
-libpci2isa_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[])
-{
- thePci2IsaBridge = new bx_pci2isa_c ();
- bx_devices.pluginPci2IsaBridge = thePci2IsaBridge;
- BX_REGISTER_DEVICE_DEVMODEL(plugin, type, thePci2IsaBridge, BX_PLUGIN_PCI2ISA);
- return(0); // Success
-}
-
- void
-libpci2isa_LTX_plugin_fini(void)
-{
-}
-
-bx_pci2isa_c::bx_pci2isa_c(void)
-{
- put("P2I");
- settype(PCI2ISALOG);
-}
-
-bx_pci2isa_c::~bx_pci2isa_c(void)
-{
- // nothing for now
- BX_DEBUG(("Exit."));
-}
-
-
- void
-bx_pci2isa_c::init(void)
-{
- // called once when bochs initializes
-
- DEV_register_pci_handlers(this, pci_read_handler, pci_write_handler,
- BX_PCI_DEVICE(1,0), "PIIX3 PCI-to-ISA bridge");
-
- DEV_register_iowrite_handler(this, write_handler, 0x00B2, "PIIX3 PCI-to-ISA bridge", 1);
- DEV_register_iowrite_handler(this, write_handler, 0x00B3, "PIIX3 PCI-to-ISA bridge", 1);
- DEV_register_iowrite_handler(this, write_handler, 0x04D0, "PIIX3 PCI-to-ISA bridge", 1);
- DEV_register_iowrite_handler(this, write_handler, 0x04D1, "PIIX3 PCI-to-ISA bridge", 1);
- DEV_register_iowrite_handler(this, write_handler, 0x0CF9, "PIIX3 PCI-to-ISA bridge", 1);
-
- DEV_register_ioread_handler(this, read_handler, 0x00B2, "PIIX3 PCI-to-ISA bridge", 1);
- DEV_register_ioread_handler(this, read_handler, 0x00B3, "PIIX3 PCI-to-ISA bridge", 1);
- DEV_register_ioread_handler(this, read_handler, 0x04D0, "PIIX3 PCI-to-ISA bridge", 1);
- DEV_register_ioread_handler(this, read_handler, 0x04D1, "PIIX3 PCI-to-ISA bridge", 1);
- DEV_register_ioread_handler(this, read_handler, 0x0CF9, "PIIX3 PCI-to-ISA bridge", 1);
-
- for (unsigned i=0; i<256; i++)
- BX_P2I_THIS s.pci_conf[i] = 0x0;
- // readonly registers
- BX_P2I_THIS s.pci_conf[0x00] = 0x86;
- BX_P2I_THIS s.pci_conf[0x01] = 0x80;
- BX_P2I_THIS s.pci_conf[0x02] = 0x00;
- BX_P2I_THIS s.pci_conf[0x03] = 0x70;
- BX_P2I_THIS s.pci_conf[0x0a] = 0x01;
- BX_P2I_THIS s.pci_conf[0x0b] = 0x06;
- BX_P2I_THIS s.pci_conf[0x0e] = 0x80;
-}
-
- void
-bx_pci2isa_c::reset(unsigned type)
-{
- BX_P2I_THIS s.pci_conf[0x04] = 0x07;
- BX_P2I_THIS s.pci_conf[0x05] = 0x00;
- BX_P2I_THIS s.pci_conf[0x06] = 0x00;
- BX_P2I_THIS s.pci_conf[0x07] = 0x02;
- BX_P2I_THIS s.pci_conf[0x4c] = 0x4d;
- BX_P2I_THIS s.pci_conf[0x4e] = 0x03;
- BX_P2I_THIS s.pci_conf[0x4f] = 0x00;
- BX_P2I_THIS s.pci_conf[0x60] = 0x80;
- BX_P2I_THIS s.pci_conf[0x69] = 0x02;
- BX_P2I_THIS s.pci_conf[0x70] = 0x80;
- BX_P2I_THIS s.pci_conf[0x76] = 0x0c;
- BX_P2I_THIS s.pci_conf[0x77] = 0x0c;
- BX_P2I_THIS s.pci_conf[0x78] = 0x02;
- BX_P2I_THIS s.pci_conf[0x79] = 0x00;
- BX_P2I_THIS s.pci_conf[0x80] = 0x00;
- BX_P2I_THIS s.pci_conf[0x82] = 0x00;
- BX_P2I_THIS s.pci_conf[0xa0] = 0x08;
- BX_P2I_THIS s.pci_conf[0xa0] = 0x08;
- BX_P2I_THIS s.pci_conf[0xa2] = 0x00;
- BX_P2I_THIS s.pci_conf[0xa3] = 0x00;
- BX_P2I_THIS s.pci_conf[0xa4] = 0x00;
- BX_P2I_THIS s.pci_conf[0xa5] = 0x00;
- BX_P2I_THIS s.pci_conf[0xa6] = 0x00;
- BX_P2I_THIS s.pci_conf[0xa7] = 0x00;
- BX_P2I_THIS s.pci_conf[0xa8] = 0x0f;
- BX_P2I_THIS s.pci_conf[0xaa] = 0x00;
- BX_P2I_THIS s.pci_conf[0xab] = 0x00;
- BX_P2I_THIS s.pci_conf[0xac] = 0x00;
- BX_P2I_THIS s.pci_conf[0xae] = 0x00;
-
- BX_P2I_THIS s.elcr1 = 0x00;
- BX_P2I_THIS s.elcr2 = 0x00;
-}
-
-
-
- // static IO port read callback handler
- // redirects to non-static class handler to avoid virtual functions
-
- Bit32u
-bx_pci2isa_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len)
-{
-#if !BX_USE_P2I_SMF
- bx_pci2isa_c *class_ptr = (bx_pci2isa_c *) this_ptr;
-
- return( class_ptr->read(address, io_len) );
-}
-
-
- Bit32u
-bx_pci2isa_c::read(Bit32u address, unsigned io_len)
-{
-#else
- UNUSED(this_ptr);
-#endif // !BX_USE_P2I_SMF
-
- switch (address) {
- case 0x00b2:
- BX_ERROR(("read: APM command register not supported yet"));
- break;
- case 0x00b3:
- BX_ERROR(("read: APM status register not supported yet"));
- break;
- case 0x04d0:
- return(BX_P2I_THIS s.elcr1);
- break;
- case 0x04d1:
- return(BX_P2I_THIS s.elcr2);
- break;
- case 0x0cf9:
- BX_ERROR(("read: CPU reset register not supported yet"));
- break;
- }
-
- return(0xffffffff);
-}
-
-
- // static IO port write callback handler
- // redirects to non-static class handler to avoid virtual functions
-
- void
-bx_pci2isa_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len)
-{
-#if !BX_USE_P2I_SMF
- bx_pci2isa_c *class_ptr = (bx_pci2isa_c *) this_ptr;
-
- class_ptr->write(address, value, io_len);
-}
-
- void
-bx_pci2isa_c::write(Bit32u address, Bit32u value, unsigned io_len)
-{
-#else
- UNUSED(this_ptr);
-#endif // !BX_USE_P2I_SMF
-
- switch (address) {
- case 0x00b2:
- BX_ERROR(("write: APM command register not supported yet"));
- break;
- case 0x00b3:
- BX_ERROR(("write: APM status register not supported yet"));
- break;
- case 0x04d0:
- BX_P2I_THIS s.elcr1 = (value & 0xf8);
- BX_ERROR(("write: ELCR1 changes have no effect yet"));
- break;
- case 0x04d1:
- BX_P2I_THIS s.elcr2 = (value & 0xde);
- BX_ERROR(("write: ELCR2 changes have no effect yet"));
- break;
- case 0x0cf9:
- BX_ERROR(("write: CPU reset register not supported yet"));
- break;
- }
-}
-
-
- // static pci configuration space read callback handler
- // redirects to non-static class handler to avoid virtual functions
-
- Bit32u
-bx_pci2isa_c::pci_read_handler(void *this_ptr, Bit8u address, unsigned io_len)
-{
-#if !BX_USE_P2I_SMF
- bx_pci2isa_c *class_ptr = (bx_pci2isa_c *) this_ptr;
-
- return( class_ptr->pci_read(address, io_len) );
-}
-
-
- Bit32u
-bx_pci2isa_c::pci_read(Bit8u address, unsigned io_len)
-{
-#else
- UNUSED(this_ptr);
-#endif // !BX_USE_P2I_SMF
-
- Bit32u value = 0;
-
- if (io_len <= 4) {
- for (unsigned i=0; i<io_len; i++) {
- value |= (BX_P2I_THIS s.pci_conf[address+i] << (i*8));
- }
- BX_DEBUG(("PIIX3 PCI-to-ISA read register 0x%02x value 0x%08x", address, value));
- return value;
- }
- else
- return(0xffffffff);
-}
-
-
- // static pci configuration space write callback handler
- // redirects to non-static class handler to avoid virtual functions
-
- void
-bx_pci2isa_c::pci_write_handler(void *this_ptr, Bit8u address, Bit32u value, unsigned io_len)
-{
-#if !BX_USE_P2I_SMF
- bx_pci2isa_c *class_ptr = (bx_pci2isa_c *) this_ptr;
-
- class_ptr->pci_write(address, value, io_len);
-}
-
- void
-bx_pci2isa_c::pci_write(Bit8u address, Bit32u value, unsigned io_len)
-{
-#else
- UNUSED(this_ptr);
-#endif // !BX_USE_P2I_SMF
-
- Bit8u value8;
-
- if (io_len <= 4) {
- for (unsigned i=0; i<io_len; i++) {
- value8 = (value >> (i*8)) & 0xFF;
- switch (address+i) {
- case 0x06:
- break;
- default:
- BX_P2I_THIS s.pci_conf[address+i] = value8;
- BX_DEBUG(("PIIX3 PCI-to-ISA write register 0x%02x value 0x%02x", address,
- value8));
- }
- }
- }
-}
-
-#endif /* BX_PCI_SUPPORT */
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: pci2isa.h,v 1.4 2002/11/09 20:51:40 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-#if BX_USE_P2I_SMF
-# define BX_P2I_SMF static
-# define BX_P2I_THIS thePci2IsaBridge->
-#else
-# define BX_P2I_SMF
-# define BX_P2I_THIS this->
-#endif
-
-
-class bx_pci2isa_c : public bx_devmodel_c {
-
-public:
- bx_pci2isa_c(void);
- ~bx_pci2isa_c(void);
- virtual void init(void);
- virtual void reset(unsigned type);
-
-private:
-
- struct {
- Bit8u pci_conf[256];
- Bit8u elcr1;
- Bit8u elcr2;
- } s;
-
- static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len);
- static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len);
- static Bit32u pci_read_handler(void *this_ptr, Bit8u address, unsigned io_len);
- static void pci_write_handler(void *this_ptr, Bit8u address, Bit32u value, unsigned io_len);
-#if !BX_USE_P2I_SMF
- Bit32u read(Bit32u address, unsigned io_len);
- void write(Bit32u address, Bit32u value, unsigned io_len);
- Bit32u pci_read(Bit8u address, unsigned io_len);
- void pci_write(Bit8u address, Bit32u value, unsigned io_len);
-#endif
- };
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: pciusb.cc,v 1.3 2003/02/06 19:09:24 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2003 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-//
-// Experimental PCI USB adapter
-// Benjamin D Lunt (fys@cybertrails.com) coded most of this usb emulation.
-// I hope to add to this code to make it more functionable.
-//
-
-// Define BX_PLUGGABLE in files that can be compiled into plugins. For
-// platforms that require a special tag on exported symbols, BX_PLUGGABLE
-// is used to know when we are exporting symbols and when we are importing.
-#define BX_PLUGGABLE
-
-#include "bochs.h"
-#if BX_PCI_SUPPORT && BX_PCI_USB_SUPPORT
-
-#define LOG_THIS theUSBDevice->
-
-bx_pciusb_c* theUSBDevice = NULL;
-
- int
-libpciusb_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[])
-{
- theUSBDevice = new bx_pciusb_c ();
- bx_devices.pluginPciUSBAdapter = theUSBDevice;
- BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theUSBDevice, BX_PLUGIN_PCIUSB);
- return 0; // Success
-}
-
- void
-libpciusb_LTX_plugin_fini(void)
-{
-}
-
-
-bx_pciusb_c::bx_pciusb_c(void)
-{
- put("USB");
- settype(PCIUSBLOG);
-}
-
-bx_pciusb_c::~bx_pciusb_c(void)
-{
- // nothing for now
- BX_DEBUG(("Exit."));
-}
-
-
- void
-bx_pciusb_c::init(void)
-{
- // called once when bochs initializes
-
- if (!bx_options.usb[0].Oenabled->get()) return;
-
- Bit16u base_ioaddr = bx_options.usb[0].Oioaddr->get();
- Bit8u irq = bx_options.usb[0].Oirq->get();
-
- DEV_register_irq(irq, "USB Hub #1");
- BX_USB_THIS hub[0].irq = irq;
-
- // Call our timer routine every 1mS (1,000uS)
- // Continuous and active
- BX_USB_THIS hub[0].timer_index =
- bx_pc_system.register_timer(this, usb_timer_handler, 1000, 1,1, "usb.timer");
-
- for (unsigned addr=base_ioaddr; addr<(unsigned)(base_ioaddr+0x14); addr++) {
- BX_DEBUG(("register read/write: 0x%04x", addr));
- DEV_register_ioread_handler(this, read_handler, addr, "USB Hub #1", 7);
- DEV_register_iowrite_handler(this, write_handler, addr, "USB Hub #1", 7);
- }
- BX_USB_THIS hub[0].base_ioaddr = base_ioaddr;
-
- DEV_register_pci_handlers(this,
- pci_read_handler,
- pci_write_handler,
- BX_PCI_DEVICE(1,2),
- "Experimental PCI USB");
-
- for (unsigned i=0; i<256; i++) {
- BX_USB_THIS hub[0].pci_conf[i] = 0x0;
- }
-
- BX_INFO(("usb1 at 0x%04x-0x%04x irq %d", base_ioaddr, base_ioaddr+0x13, irq));
-}
-
- void
-bx_pciusb_c::reset(unsigned type)
-{
- unsigned i;
-
- static const struct reset_vals_t {
- unsigned addr;
- unsigned char val;
- } reset_vals[] = {
- { 0x00, 0x86 }, { 0x01, 0x80 }, // 0x8086 = vendor
- { 0x02, 0x20 }, { 0x03, 0x70 }, // 0x7020 = device
- { 0x04, 0x05 }, { 0x05, 0x00 }, // command_io
- { 0x06, 0x80 }, { 0x07, 0x02 }, // status
- { 0x08, 0x01 }, // revision number
- { 0x09, 0x00 }, // interface
- { 0x0a, 0x03 }, // class_sub USB Host Controller
- { 0x0b, 0x0c }, // class_base Serial Bus Controller
- { 0x0D, 0x20 }, // bus latency
- { 0x0e, 0x00 }, // header_type_generic
- // address space 0x20 - 0x23
- { 0x20, ((bx_options.usb[0].Oioaddr->get() & 0xE0) | 0x01) },
- { 0x21, (bx_options.usb[0].Oioaddr->get() >> 8) },
- { 0x22, 0x00 }, { 0x23, 0x00 },
- { 0x3c, bx_options.usb[0].Oirq->get() }, // IRQ
- { 0x3d, 0x04 }, // INT
- { 0x6a, 0x01 }, // USB clock
- { 0xc1, 0x20 } // PIRQ enable
-
- };
- for (i = 0; i < sizeof(reset_vals) / sizeof(*reset_vals); ++i) {
- BX_USB_THIS hub[0].pci_conf[reset_vals[i].addr] = reset_vals[i].val;
- }
-
- // reset locals
- BX_USB_THIS global_reset = 0;
-
- // Put the USB registers into their RESET state
- for (i=0; i<BX_USB_CONFDEV; i++) {
- BX_USB_THIS hub[i].usb_command.max_packet_size = 0;
- BX_USB_THIS hub[i].usb_command.configured = 0;
- BX_USB_THIS hub[i].usb_command.debug = 0;
- BX_USB_THIS hub[i].usb_command.resume = 0;
- BX_USB_THIS hub[i].usb_command.suspend = 1;
- BX_USB_THIS hub[i].usb_command.host_reset = 0;
- BX_USB_THIS hub[i].usb_command.reset = 0;
- BX_USB_THIS hub[i].usb_command.schedule = 0;
- BX_USB_THIS hub[i].usb_status.error_interrupt = 0;
- BX_USB_THIS hub[i].usb_status.host_error = 0;
- BX_USB_THIS hub[i].usb_status.host_halted = 0;
- BX_USB_THIS hub[i].usb_status.interrupt = 0;
- BX_USB_THIS hub[i].usb_status.pci_error = 0;
- BX_USB_THIS hub[i].usb_status.resume = 0;
- BX_USB_THIS hub[i].usb_enable.short_packet = 0;
- BX_USB_THIS hub[i].usb_enable.on_complete = 0;
- BX_USB_THIS hub[i].usb_enable.resume = 0;
- BX_USB_THIS hub[i].usb_enable.timeout_crc = 0;
- BX_USB_THIS hub[i].usb_frame_num.frame_num = 0x0000;
- BX_USB_THIS hub[i].usb_frame_base.frame_base = 0x00000000;
- BX_USB_THIS hub[i].usb_sof.sof_timing = 0x40;
- for (unsigned j=0; j<USB_NUM_PORTS; j++) {
- BX_USB_THIS hub[i].usb_port[j].connect_changed = 0;
- BX_USB_THIS hub[i].usb_port[j].line_dminus = 0;
- BX_USB_THIS hub[i].usb_port[j].line_dplus = 0;
- BX_USB_THIS hub[i].usb_port[j].low_speed = 0;
- BX_USB_THIS hub[i].usb_port[j].reset = 0;
- BX_USB_THIS hub[i].usb_port[j].resume = 0;
- BX_USB_THIS hub[i].usb_port[j].suspend = 0;
- BX_USB_THIS hub[i].usb_port[j].enabled = 0;
- BX_USB_THIS hub[i].usb_port[j].able_changed = 0;
- BX_USB_THIS hub[i].usb_port[j].status = 0;
- }
- }
-}
-
-
- // static IO port read callback handler
- // redirects to non-static class handler to avoid virtual functions
-
- Bit32u
-bx_pciusb_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len)
-{
-#if !BX_USE_PCIUSB_SMF
- bx_pciusb_c *class_ptr = (bx_pciusb_c *) this_ptr;
-
- return( class_ptr->read(address, io_len) );
-}
-
-
- Bit32u
-bx_pciusb_c::read(Bit32u address, unsigned io_len)
-{
-#else
- UNUSED(this_ptr);
-#endif // !BX_USE_PCIUSB_SMF
- Bit32u val = 0x0;
- Bit8u offset,port;
-
- BX_DEBUG(("register read from address 0x%04x - ", (unsigned) address));
-
- offset = address - BX_USB_THIS hub[0].base_ioaddr;
-
- switch (offset) {
- case 0x0C: // Start of Frame Modify
- case 0x11: // port0 (high byte read)
- case 0x13: // port1 (high byte read)
- if (io_len != 1)
- BX_PANIC(("io read from port 0x%04x, bad len=%u", (unsigned) address, (unsigned) io_len));
- break;
- case 0x10: // port0
- case 0x12: // port1
- if ((io_len < 1) || (io_len > 2))
- BX_PANIC(("io read from port 0x%04x, bad len=%u", (unsigned) address, (unsigned) io_len));
- break;
- case 0x00: // command register (16-bit)
- case 0x02: // status register (16-bit)
- case 0x04: // interrupt enable register (1-bit)
- case 0x06: // frame number register (16-bit)
- if (io_len != 2)
- BX_PANIC(("io read from port 0x%04x, bad len=%u", (unsigned) address, (unsigned) io_len));
- break;
- case 0x08: // frame base register (32-bit)
- if (io_len != 4)
- BX_PANIC(("io read from port 0x%04x, bad len=%u", (unsigned) address, (unsigned) io_len));
- break;
- }
-
- switch (offset) {
- case 0x00: // command register (16-bit)
- val = BX_USB_THIS hub[0].usb_command.max_packet_size << 7
- | BX_USB_THIS hub[0].usb_command.configured << 6
- | BX_USB_THIS hub[0].usb_command.debug << 5
- | BX_USB_THIS hub[0].usb_command.resume << 4
- | BX_USB_THIS hub[0].usb_command.suspend << 3
- | BX_USB_THIS hub[0].usb_command.reset << 2
- | BX_USB_THIS hub[0].usb_command.host_reset << 1
- | BX_USB_THIS hub[0].usb_command.schedule;
- break;
-
- case 0x02: // status register (16-bit)
- val = BX_USB_THIS hub[0].usb_status.host_halted << 5
- | BX_USB_THIS hub[0].usb_status.host_error << 4
- | BX_USB_THIS hub[0].usb_status.pci_error << 3
- | BX_USB_THIS hub[0].usb_status.resume << 2
- | BX_USB_THIS hub[0].usb_status.error_interrupt << 1
- | BX_USB_THIS hub[0].usb_status.interrupt;
- break;
-
- case 0x04: // interrupt enable register (16-bit)
- val = BX_USB_THIS hub[0].usb_enable.short_packet << 3
- | BX_USB_THIS hub[0].usb_enable.on_complete << 2
- | BX_USB_THIS hub[0].usb_enable.resume << 1
- | BX_USB_THIS hub[0].usb_enable.timeout_crc;
- break;
-
- case 0x06: // frame number register (16-bit)
- val = BX_USB_THIS hub[0].usb_frame_num.frame_num;
- break;
-
- case 0x08: // frame base register (32-bit)
- val = BX_USB_THIS hub[0].usb_frame_base.frame_base;
- break;
-
- case 0x0C: // start of Frame Modify register (8-bit)
- val = BX_USB_THIS hub[0].usb_sof.sof_timing;
- break;
-
- case 0x10: // port0
- case 0x12: // port1
- port = (offset & 0x0F) >> 1;
- if (port < USB_NUM_PORTS) {
- val = BX_USB_THIS hub[0].usb_port[port].suspend << 12
- | BX_USB_THIS hub[0].usb_port[port].reset << 9
- | BX_USB_THIS hub[0].usb_port[port].low_speed << 8
- | 1 << 7
- | BX_USB_THIS hub[0].usb_port[port].resume << 6
- | BX_USB_THIS hub[0].usb_port[port].line_dplus << 5
- | BX_USB_THIS hub[0].usb_port[port].line_dminus << 4
- | BX_USB_THIS hub[0].usb_port[port].able_changed << 3
- | BX_USB_THIS hub[0].usb_port[port].enabled << 2
- | BX_USB_THIS hub[0].usb_port[port].connect_changed << 1
- | BX_USB_THIS hub[0].usb_port[port].status;
- break;
- } // else fall through to default
-
- default:
- val = 0; // keep compiler happy
- BX_PANIC(("unsupported io read from address=0x%04x!", (unsigned) address));
- break;
- }
-
- BX_DEBUG(("val = 0x%08x", (Bit32u) val));
-
- return(val);
-}
-
-
- // static IO port write callback handler
- // redirects to non-static class handler to avoid virtual functions
-
- void
-bx_pciusb_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len)
-{
-#if !BX_USE_PCIUSB_SMF
- bx_pciusb_c *class_ptr = (bx_pciusb_c *) this_ptr;
-
- class_ptr->write(address, value, io_len);
-}
-
- void
-bx_pciusb_c::write(Bit32u address, Bit32u value, unsigned io_len)
-{
-#else
- UNUSED(this_ptr);
-#endif // !BX_USE_PCIUSB_SMF
- Bit8u offset,port;
-
- BX_DEBUG(("register write to address 0x%04x - ", (unsigned) address));
-
- offset = address - BX_USB_THIS hub[0].base_ioaddr;
-
- switch (offset) {
- case 0x0C: // Start of Frame Modify
- if (io_len != 1)
- BX_PANIC(("io write to port 0x%04x, bad len=%u", (unsigned) address, (unsigned) io_len));
- break;
- case 0x00: // command register (16-bit)
- case 0x02: // status register (16-bit)
- case 0x04: // interrupt enable register (1-bit)
- case 0x06: // frame number register (16-bit)
- case 0x10: // port0
- case 0x12: // port1
- if (io_len != 2)
- BX_PANIC(("io write to port 0x%04x, bad len=%u", (unsigned) address, (unsigned) io_len));
- break;
- case 0x08: // frame base register (32-bit)
- if (io_len != 4)
- BX_PANIC(("io write to port 0x%04x, bad len=%u", (unsigned) address, (unsigned) io_len));
- break;
- }
-
- switch (offset) {
- case 0x00: // command register (16-bit) (R/W)
- if (value & 0xFF00)
- BX_ERROR(("write to command register with bits 15:8 not zero: 0x%04x", value));
-
- BX_USB_THIS hub[0].usb_command.max_packet_size = (value & 0x80) ? 1: 0;
- BX_USB_THIS hub[0].usb_command.configured = (value & 0x40) ? 1: 0;
- BX_USB_THIS hub[0].usb_command.debug = (value & 0x20) ? 1: 0;
- BX_USB_THIS hub[0].usb_command.resume = (value & 0x10) ? 1: 0;
- BX_USB_THIS hub[0].usb_command.suspend = (value & 0x08) ? 1: 0;
- BX_USB_THIS hub[0].usb_command.reset = (value & 0x04) ? 1: 0;
- BX_USB_THIS hub[0].usb_command.host_reset = (value & 0x02) ? 1: 0;
- BX_USB_THIS hub[0].usb_command.schedule = (value & 0x01) ? 1: 0;
-
- // If software set the reset bit, we need to set reset bit of each port for 10ms.
- if (BX_USB_THIS hub[0].usb_command.reset)
- BX_USB_THIS global_reset = 10;
-
- // If host_reset then reset all registers, etc.
- if (BX_USB_THIS hub[0].usb_command.host_reset)
- BX_USB_THIS reset(0);
-
- // If Run/Stop, identify in log and ignore
- if (BX_USB_THIS hub[0].usb_command.schedule)
- BX_INFO(("Software set Schedule bit in Command register"));
-
- // If Debug mode set, panic. Not implemented
- if (BX_USB_THIS hub[0].usb_command.debug)
- BX_PANIC(("Software set DEBUG bit in Command register. Not implemented"));
-
- break;
-
- case 0x02: // status register (16-bit) (R/WC)
- if (value & 0xFFC0)
- BX_ERROR(("write to status register with bits 15:6 not zero: 0x%04x", value));
-
- BX_USB_THIS hub[0].usb_status.host_halted = (value & 0x20) ? 0: BX_USB_THIS hub[0].usb_status.host_halted;
- BX_USB_THIS hub[0].usb_status.host_error = (value & 0x10) ? 0: BX_USB_THIS hub[0].usb_status.host_error;
- BX_USB_THIS hub[0].usb_status.pci_error = (value & 0x08) ? 0: BX_USB_THIS hub[0].usb_status.pci_error;
- BX_USB_THIS hub[0].usb_status.resume = (value & 0x04) ? 0: BX_USB_THIS hub[0].usb_status.resume;
- BX_USB_THIS hub[0].usb_status.error_interrupt = (value & 0x02) ? 0: BX_USB_THIS hub[0].usb_status.error_interrupt;
- BX_USB_THIS hub[0].usb_status.interrupt = (value & 0x01) ? 0: BX_USB_THIS hub[0].usb_status.interrupt;
- break;
-
- case 0x04: // interrupt enable register (16-bit)
- if (value & 0xFFF0)
- BX_ERROR(("write to interrupt enable register with bits 15:4 not zero: 0x%04x", value));
-
- BX_USB_THIS hub[0].usb_enable.short_packet = (value & 0x08) ? 1: 0;
- BX_USB_THIS hub[0].usb_enable.on_complete = (value & 0x04) ? 1: 0;
- BX_USB_THIS hub[0].usb_enable.resume = (value & 0x02) ? 1: 0;
- BX_USB_THIS hub[0].usb_enable.timeout_crc = (value & 0x01) ? 1: 0;
-
- // For now, we will just ignore these being set since we never raise the IRQ
-
- break;
-
- case 0x06: // frame number register (16-bit)
- if (value & 0xF800)
- BX_ERROR(("write to frame number register with bits 15:11 not zero: 0x%04x", value));
-
- if (BX_USB_THIS hub[0].usb_status.host_halted)
- BX_USB_THIS hub[0].usb_frame_num.frame_num = value;
- else
- // ignored by the hardward, but lets report it anyway
- BX_ERROR(("write to frame number register with STATUS.HALTED == 0"));
-
- break;
-
- case 0x08: // frame base register (32-bit)
- if (value & 0xFFF)
- BX_PANIC(("write to frame base register with bits 11:0 not zero: 0x%08x", value));
-
- BX_USB_THIS hub[0].usb_frame_base.frame_base = value;
- break;
-
- case 0x0C: // start of Frame Modify register (8-bit)
- if (value & 0x80)
- BX_ERROR(("write to SOF Modify register with bit 7 not zero: 0x%04x", value));
-
- BX_USB_THIS hub[0].usb_sof.sof_timing = value;
- break;
-
- case 0x10: // port0
- case 0x12: // port1
- port = (offset & 0x0F) >> 1;
- if (port < USB_NUM_PORTS) {
- if (value & ((1<<5) | (1<<4) | (1<<0)))
- BX_PANIC(("write to one or more read-only bits in port%d register: 0x%04x", port, value));
- if (!(value & (1<<7)))
- BX_ERROR(("write to port%d register bit 7 = 0", port));
- if (value & (1<<8))
- BX_INFO(("write to bit 8 in port%d register ignored", port));
- if (value & (1<<2))
- BX_INFO(("port%d enabled ignored. Not implemented", port));
- if ((value & (1<<12)) && BX_USB_THIS hub[0].usb_command.suspend)
- BX_ERROR(("write to port%d register bit 12 when in Global-Suspend", port));
-
- BX_USB_THIS hub[0].usb_port[port].suspend = (value & (1<<12)) ? 1 : 0;
- BX_USB_THIS hub[0].usb_port[port].reset = (value & (1<<9)) ? 1 : 0;
- BX_USB_THIS hub[0].usb_port[port].resume = (value & (1<<6)) ? 1 : 0;
- BX_USB_THIS hub[0].usb_port[port].able_changed = (value & (1<<3)) ? 0 : BX_USB_THIS hub[0].usb_port[0].able_changed;
- BX_USB_THIS hub[0].usb_port[port].enabled = (value & (1<<2)) ? 1 : 0;
- BX_USB_THIS hub[0].usb_port[port].connect_changed = (value & (1<<1)) ? 0 : BX_USB_THIS hub[0].usb_port[0].connect_changed;
- break;
- }
- // else fall through to default
-
- default:
- BX_PANIC(("unsupported io write to address=0x%04x!", (unsigned) address));
- break;
- }
-}
-
-void bx_pciusb_c::usb_timer_handler(void *this_ptr)
-{
- bx_pciusb_c *class_ptr = (bx_pciusb_c *) this_ptr;
- class_ptr->usb_timer();
-}
-
-// Called once every 1ms
-void bx_pciusb_c::usb_timer(void)
-{
- int i;
-
- // The Frame Number Register is incremented every 1ms ?????????
- // Needs more work and investigation on this.
- BX_USB_THIS hub[0].usb_frame_num.frame_num++;
- BX_USB_THIS hub[0].usb_frame_num.frame_num &= (1024-1);
-
- // If the "global reset" bit was set by software, we need
- // to set the reset bit in each "active" port for 10ms
- if (BX_USB_THIS global_reset) {
- for (i=0; i<USB_NUM_PORTS; i++) {
- BX_USB_THIS hub[0].usb_port[i].able_changed = 0;
- BX_USB_THIS hub[0].usb_port[i].connect_changed = 0;
- BX_USB_THIS hub[0].usb_port[i].enabled = 0;
- BX_USB_THIS hub[0].usb_port[i].line_dminus = 0;
- BX_USB_THIS hub[0].usb_port[i].line_dplus = 0;
- BX_USB_THIS hub[0].usb_port[i].low_speed = 0;
- BX_USB_THIS hub[0].usb_port[i].reset = 1;
- BX_USB_THIS hub[0].usb_port[i].resume = 0;
- BX_USB_THIS hub[0].usb_port[i].status = 0;
- BX_USB_THIS hub[0].usb_port[i].suspend = 0;
- }
- BX_USB_THIS global_reset--;
- } else {
- for (i=0; i<USB_NUM_PORTS; i++)
- BX_USB_THIS hub[0].usb_port[i].reset = 0;
- }
-
- // If command.schedule = 0, then we need to set Status.Halted
- if (!BX_USB_THIS hub[0].usb_command.schedule)
- BX_USB_THIS hub[0].usb_status.host_halted = 1;
-
-
- // TODO:
- // If ins Global_Suspend mode and any of usb_port[i] bits 6,3, or 1 are set,
- // we need to issue a Global_Resume (set the global resume bit).
- // However, since we don't do anything, let's not.
-
-}
-
- // static pci configuration space read callback handler
- // redirects to non-static class handler to avoid virtual functions
-
- Bit32u
-bx_pciusb_c::pci_read_handler(void *this_ptr, Bit8u address, unsigned io_len)
-{
-#if !BX_USE_PCIUSB_SMF
- bx_pciusb_c *class_ptr = (bx_pciusb_c *) this_ptr;
-
- return class_ptr->pci_read(address, io_len);
-}
-
-
- Bit32u
-bx_pciusb_c::pci_read(Bit8u address, unsigned io_len)
-{
-#else
- UNUSED(this_ptr);
-#endif // !BX_USE_PCIUSB_SMF
-
- Bit32u value = 0;
-
- if (io_len > 4 || io_len == 0) {
- BX_ERROR(("Experimental USB PCI read register 0x%02x, len=%u !",
- (unsigned) address, (unsigned) io_len));
- return 0xffffffff;
- }
-
- const char* pszName = " ";
- switch (address) {
- case 0x00: if (io_len == 2) {
- pszName = "(vendor id) ";
- } else if (io_len == 4) {
- pszName = "(vendor + device) ";
- }
- break;
- case 0x04: if (io_len == 2) {
- pszName = "(command) ";
- } else if (io_len == 4) {
- pszName = "(command+status) ";
- }
- break;
- case 0x08: if (io_len == 1) {
- pszName = "(revision id) ";
- } else if (io_len == 4) {
- pszName = "(rev.+class code) ";
- }
- break;
- case 0x0c: pszName = "(cache line size) "; break;
- case 0x20: pszName = "(base address) "; break;
- case 0x28: pszName = "(cardbus cis) "; break;
- case 0x2c: pszName = "(subsys. vendor+) "; break;
- case 0x30: pszName = "(rom base) "; break;
- case 0x3c: pszName = "(interrupt line+) "; break;
- case 0x3d: pszName = "(interrupt pin) "; break;
- }
-
- // This odd code is to display only what bytes actually were read.
- char szTmp[9];
- char szTmp2[3];
- szTmp[0] = '\0';
- szTmp2[0] = '\0';
- for (unsigned i=0; i<io_len; i++) {
- value |= (BX_USB_THIS hub[0].pci_conf[address+i] << (i*8));
- sprintf(szTmp2, "%02x", (BX_USB_THIS hub[0].pci_conf[address+i]));
- strrev(szTmp2);
- strcat(szTmp, szTmp2);
- }
- strrev(szTmp);
- BX_DEBUG(("Experimental USB PCI read register 0x%02x %svalue 0x%s",
- address, pszName, szTmp));
- return value;
-}
-
-
- // static pci configuration space write callback handler
- // redirects to non-static class handler to avoid virtual functions
-
- void
-bx_pciusb_c::pci_write_handler(void *this_ptr, Bit8u address, Bit32u value, unsigned io_len)
-{
-#if !BX_USE_PCIUSB_SMF
- bx_pciusb_c *class_ptr = (bx_pciusb_c *) this_ptr;
-
- class_ptr->pci_write(address, value, io_len);
-}
-
- void
-bx_pciusb_c::pci_write(Bit8u address, Bit32u value, unsigned io_len)
-{
-#else
- UNUSED(this_ptr);
-#endif // !BX_USE_PCIUSB_SMF
-
- if (io_len > 4 || io_len == 0) {
- BX_ERROR(("Experimental USB PCI write register 0x%02x, len=%u !",
- (unsigned) address, (unsigned) io_len));
- return;
- }
-
- // This odd code is to display only what bytes actually were written.
- char szTmp[9];
- char szTmp2[3];
- szTmp[0] = '\0';
- szTmp2[0] = '\0';
- for (unsigned i=0; i<io_len; i++) {
- const Bit8u value8 = (value >> (i*8)) & 0xFF;
- switch (address+i) {
- case 0x20: // Base address
- BX_USB_THIS hub[0].pci_conf[address+i] = (value8 & 0xe0) | 0x01;
- sprintf(szTmp2, "%02x", (value8 & 0xe0) | 0x01);
- break;
- case 0x10: // Reserved
- case 0x11: //
- case 0x12: //
- case 0x13: //
- case 0x14: //
- case 0x15: //
- case 0x16: //
- case 0x17: //
- case 0x18: //
- case 0x19: //
- case 0x1a: //
- case 0x1b: //
- case 0x1c: //
- case 0x1d: //
- case 0x1e: //
- case 0x1f: //
- case 0x22: // Always 0
- case 0x23: //
- case 0x24: // Reserved
- case 0x25: //
- case 0x26: //
- case 0x27: //
- case 0x30: // Oh, no, you're not writing to rom_base!
- case 0x31: //
- case 0x32: //
- case 0x33: //
- case 0x3d: //
- case 0x05: // disallowing write to command hi-byte
- case 0x06: // disallowing write to status lo-byte (is that expected?)
- strcpy(szTmp2, "..");
- break;
- default:
- BX_USB_THIS hub[0].pci_conf[address+i] = value8;
- sprintf(szTmp2, "%02x", value8);
- }
- strrev(szTmp2);
- strcat(szTmp, szTmp2);
- }
- strrev(szTmp);
- BX_DEBUG(("Experimental USB PCI write register 0x%02x value 0x%s", address, szTmp));
-}
-
-#endif // BX_PCI_SUPPORT && BX_PCI_USB_SUPPORT
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: pciusb.h,v 1.1 2003/01/28 16:58:10 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2003 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-// Benjamin D Lunt (fys@cybertrails.com) coded most of this usb emulation.
-// I hope to add to this code to make it more functionable.
-//
-
-#if BX_USE_PCIUSB_SMF
-# define BX_USB_THIS theUSBDevice->
-#else
-# define BX_USB_THIS this->
-#endif
-
-#define BX_USB_MAXDEV 1
-#define BX_USB_CONFDEV 1 /* only 1 USB hub currently */
-
-#define USB_NUM_PORTS 2 /* UHCI supports 2 ports per root hub */
-
-typedef struct {
-
- Bit16u base_ioaddr;
- Bit8u irq;
- int timer_index;
-
- // Registers
- // Base + 0x00 Command register
- // Base + 0x02 Status register
- // Base + 0x04 Interrupt Enable register
- // Base + 0x06 Frame Number register
- // Base + 0x08 Frame Base Register (32-bit)
- // Base + 0x0C Start of Frame Modify register
- // Base + 0x0D
- // Base + 0x0E
- // Base + 0x0F
- // Base + 0x10 Eight(?) 16-bit ports (one for each port on hub)
-
- // Bit reps of registers above
- // Command Register
- // Bits 15-8 are reserved
- // Bit 7 = Maximum packet size
- // Bit 6 = Host Controller has been configured (set by software)
- // Bit 5 = software debug mode
- // Bit 4 = force global resume
- // Bit 3 = enter global suspend mode
- // Bit 2 = global reset
- // Bit 1 = host controller reset
- // Bit 0 = run/stop schedule
- struct {
- bx_bool max_packet_size; //(bit 7) 0 = 32 bytes, 1 = 64 bytes
- bx_bool configured; //(bit 6)
- bx_bool debug; //(bit 5)
- bx_bool resume; //(bit 4)
- bx_bool suspend; //(bit 3)
- bx_bool reset; //(bit 2)
- bx_bool host_reset; //(bit 1)
- bx_bool schedule; //(bit 0) 0 = Stop, 1 = Run
- } usb_command;
-
- // Status Register
- // Bits 15-6 are reserved
- // Bit 5 = Host controller halted
- // Bit 4 = Host controller process error
- // Bit 3 = PCI Bus error
- // Bit 2 = resume received
- // Bit 1 = USB error interrupt
- // Bit 0 = USB interrupt
- struct {
- bx_bool host_halted; //(bit 5)
- bx_bool host_error; //(bit 4)
- bx_bool pci_error; //(bit 3)
- bx_bool resume; //(bit 2)
- bx_bool error_interrupt; //(bit 1)
- bx_bool interrupt; //(bit 0)
- } usb_status;
-
- // Interrupt Enable Register
- // Bits 15-4 are reserved
- // Bit 3 = enable short packet interrupts
- // Bit 2 = enable interrupt On Complete
- // Bit 1 = enable resume
- // Bit 0 = enable timeout/crc
- struct {
- bx_bool short_packet; //(bit 3)
- bx_bool on_complete; //(bit 2)
- bx_bool resume; //(bit 1)
- bx_bool timeout_crc; //(bit 0)
- } usb_enable;
-
- // Frame Number Register
- // Bits 15-11 are reserved
- // Bits 10-0 Frame List Current Index/Frame Number
- struct {
- Bit16u frame_num;
- } usb_frame_num;
-
- // Frame List Base Address Register
- // Bits 31-12 Base
- // Bits 11-0 *must* be zeros when written to
- struct {
- Bit32u frame_base;
- } usb_frame_base;
-
- // Start of Frame Modify Register
- // Bit 7 reserved
- // Bits 6-0 SOF timing value (default 64)
- // SOF cycle time equals 11936+timing value
- struct {
- Bit8u sof_timing;
- } usb_sof;
-
- // Port Register (0-1)
- // Bits 15-13 are reserved
- // Bit 12 suspend port
- // Bit 11-10 are reserved
- // Bit 9 port in reset state
- // Bit 8 low-speed device is attached (read-only)
- // Bit 7 reserved
- // Bit 6 resume detected (read-only)
- // Bit 5 line-status D+ (read-only)
- // Bit 4 line-status D- (read-only)
- // Bit 3 port enabled/disable status has changed
- // (write 1 to this bit to clear it)
- // Bit 2 port is enabled
- // Bit 1 connect status has changed
- // (write 1 to this bit to clear it)
- // Bit 0 current connect status (read-only)
- // Can only write in WORD sizes (Read in byte sizes???)
- struct {
- bx_bool suspend;
- bx_bool reset;
- bx_bool low_speed;
- bx_bool resume;
- bx_bool line_dplus;
- bx_bool line_dminus;
- bx_bool able_changed;
- bx_bool enabled;
- bx_bool connect_changed;
- bx_bool status;
- } usb_port[USB_NUM_PORTS];
-
- Bit8u pci_conf[256];
-
-} bx_usb_t;
-
-
-class bx_pciusb_c : public bx_devmodel_c
-{
-public:
- bx_pciusb_c(void);
- ~bx_pciusb_c(void);
- virtual void init(void);
- virtual void reset(unsigned type);
-
-private:
-
- bx_usb_t hub[BX_USB_MAXDEV];
- Bit8u global_reset;
-
- static void usb_timer_handler(void *);
- void usb_timer(void);
-
- static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len);
- static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len);
- static Bit32u pci_read_handler(void *this_ptr, Bit8u address, unsigned io_len);
- static void pci_write_handler(void *this_ptr, Bit8u address, Bit32u value, unsigned io_len);
-#if !BX_USE_PCIUSB_SMF
- Bit32u read(Bit32u address, unsigned io_len);
- void write(Bit32u address, Bit32u value, unsigned io_len);
- Bit32u pci_read(Bit8u address, unsigned io_len);
- void pci_write(Bit8u address, Bit32u value, unsigned io_len);
-#endif
-};
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: pcivga.cc,v 1.2 2003/01/23 19:31:28 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002,2003 Mike Nordell
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-//
-// Experimental PCI VGA adapter
-//
-
-// Note: This "driver" was created for the SOLE PURPOSE of getting BeOS
-// to boot. It currently does NOTHING more than presenting a generic VGA
-// device on the PCI bus. ALL gfx in/out-put is still handled by the VGA code.
-// Furthermore, almost all of the PCI registers are currently acting like RAM.
-
-
-// Define BX_PLUGGABLE in files that can be compiled into plugins. For
-// platforms that require a special tag on exported symbols, BX_PLUGGABLE
-// is used to know when we are exporting symbols and when we are importing.
-#define BX_PLUGGABLE
-
-#include "bochs.h"
-#if BX_PCI_SUPPORT && BX_PCI_VGA_SUPPORT
-
-#define LOG_THIS thePciVgaAdapter->
-
-bx_pcivga_c* thePciVgaAdapter = 0;
-
- int
-libpcivga_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[])
-{
- thePciVgaAdapter = new bx_pcivga_c ();
- bx_devices.pluginPciVgaAdapter = thePciVgaAdapter;
- BX_REGISTER_DEVICE_DEVMODEL(plugin, type, thePciVgaAdapter, BX_PLUGIN_PCIVGA);
- return 0; // Success
-}
-
- void
-libpcivga_LTX_plugin_fini(void)
-{
-}
-
-
-bx_pcivga_c::bx_pcivga_c(void)
-{
- put("PCIVGA");
- settype(PCIVGALOG);
-}
-
-bx_pcivga_c::~bx_pcivga_c(void)
-{
- // nothing for now
- BX_DEBUG(("Exit."));
-}
-
-
- void
-bx_pcivga_c::init(void)
-{
- // called once when bochs initializes
-
- DEV_register_pci_handlers(this,
- pci_read_handler,
- pci_write_handler,
- BX_PCI_DEVICE(2,0),
- "Experimental PCI VGA");
-
- for (unsigned i=0; i<256; i++) {
- BX_PCIVGA_THIS s.pci_conf[i] = 0x0;
- }
-
- // readonly registers
- static const struct init_vals_t {
- unsigned addr;
- unsigned char val;
- } init_vals[] = {
- // Note that the values for vendor and device id are selected at random!
- // There might actually be "real" values for "experimental" vendor and
- // device that should be used!
- { 0x00, 0x34 }, { 0x01, 0x12 }, // 0x1234 - experimental vendor
- { 0x02, 0x11 }, { 0x03, 0x11 }, // 0x1111 - experimental device
- { 0x0a, 0x00 }, // class_sub VGA controller
- { 0x0b, 0x03 }, // class_base display
- { 0x0e, 0x00 } // header_type_generic
- };
- for (unsigned i = 0; i < sizeof(init_vals) / sizeof(*init_vals); ++i) {
- BX_PCIVGA_THIS s.pci_conf[init_vals[i].addr] = init_vals[i].val;
- }
-}
-
- void
-bx_pcivga_c::reset(unsigned type)
-{
- static const struct reset_vals_t {
- unsigned addr;
- unsigned char val;
- } reset_vals[] = {
- { 0x04, 0x01 }, { 0x05, 0x00 }, // command_io
- { 0x06, 0x00 }, { 0x07, 0x02 } // status_devsel_medium
- };
- for (unsigned i = 0; i < sizeof(reset_vals) / sizeof(*reset_vals); ++i) {
- BX_PCIVGA_THIS s.pci_conf[reset_vals[i].addr] = reset_vals[i].val;
- }
-}
-
-
- // static pci configuration space read callback handler
- // redirects to non-static class handler to avoid virtual functions
-
- Bit32u
-bx_pcivga_c::pci_read_handler(void *this_ptr, Bit8u address, unsigned io_len)
-{
-#if !BX_USE_PCIVGA_SMF
- bx_pcivga_c *class_ptr = (bx_pcivga_c *) this_ptr;
-
- return class_ptr->pci_read(address, io_len);
-}
-
-
- Bit32u
-bx_pcivga_c::pci_read(Bit8u address, unsigned io_len)
-{
-#else
- UNUSED(this_ptr);
-#endif // !BX_USE_PCIVGA_SMF
-
- Bit32u value = 0;
-
- if (io_len > 4 || io_len == 0) {
- BX_DEBUG(("Experimental PCIVGA read register 0x%02x, len=%u !",
- (unsigned) address, (unsigned) io_len));
- return 0xffffffff;
- }
-
- const char* pszName = " ";
- switch (address) {
- case 0x00: if (io_len == 2) {
- pszName = "(vendor id) ";
- } else if (io_len == 4) {
- pszName = "(vendor + device) ";
- }
- break;
- case 0x04: if (io_len == 2) {
- pszName = "(command) ";
- } else if (io_len == 4) {
- pszName = "(command+status) ";
- }
- break;
- case 0x08: if (io_len == 1) {
- pszName = "(revision id) ";
- } else if (io_len == 4) {
- pszName = "(rev.+class code) ";
- }
- break;
- case 0x0c: pszName = "(cache line size) "; break;
- case 0x28: pszName = "(cardbus cis) "; break;
- case 0x2c: pszName = "(subsys. vendor+) "; break;
- case 0x30: pszName = "(rom base) "; break;
- case 0x3c: pszName = "(interrupt line+) "; break;
- case 0x3d: pszName = "(interrupt pin) "; break;
- }
-
- // This odd code is to display only what bytes actually were read.
- char szTmp[9];
- char szTmp2[3];
- szTmp[0] = '\0';
- szTmp2[0] = '\0';
- for (unsigned i=0; i<io_len; i++) {
- value |= (BX_PCIVGA_THIS s.pci_conf[address+i] << (i*8));
-
- sprintf(szTmp2, "%02x", (BX_PCIVGA_THIS s.pci_conf[address+i]));
- strrev(szTmp2);
- strcat(szTmp, szTmp2);
- }
- strrev(szTmp);
- BX_DEBUG(("Experimental PCIVGA read register 0x%02x %svalue 0x%s",
- address, pszName, szTmp));
- return value;
-}
-
-
- // static pci configuration space write callback handler
- // redirects to non-static class handler to avoid virtual functions
-
- void
-bx_pcivga_c::pci_write_handler(void *this_ptr, Bit8u address, Bit32u value, unsigned io_len)
-{
-#if !BX_USE_PCIVGA_SMF
- bx_pcivga_c *class_ptr = (bx_pcivga_c *) this_ptr;
-
- class_ptr->pci_write(address, value, io_len);
-}
-
- void
-bx_pcivga_c::pci_write(Bit8u address, Bit32u value, unsigned io_len)
-{
-#else
- UNUSED(this_ptr);
-#endif // !BX_USE_PCIVGA_SMF
-
- if (io_len > 4 || io_len == 0) {
- BX_DEBUG(("Experimental PCIVGA write register 0x%02x, len=%u !",
- (unsigned) address, (unsigned) io_len));
- return;
- }
-
- // This odd code is to display only what bytes actually were written.
- char szTmp[9];
- char szTmp2[3];
- szTmp[0] = '\0';
- szTmp2[0] = '\0';
- for (unsigned i=0; i<io_len; i++) {
- const Bit8u value8 = (value >> (i*8)) & 0xFF;
- switch (address+i) {
- case 0x30: // Oh, no, you're not writing to rom_base!
- case 0x31: //
- case 0x32: //
- case 0x33: //
- case 0x04: // disallowing write to command
- case 0x06: // disallowing write to status lo-byte (is that expected?)
- strcpy(szTmp2, "..");
- break;
- default:
- BX_PCIVGA_THIS s.pci_conf[address+i] = value8;
- sprintf(szTmp2, "%02x", value8);
- }
- strrev(szTmp2);
- strcat(szTmp, szTmp2);
- }
- strrev(szTmp);
- BX_DEBUG(("Experimental PCIVGA write register 0x%02x value 0x%s", address, szTmp));
-}
-
-#endif // BX_PCI_SUPPORT && BX_PCI_VGA_SUPPORT
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: pcivga.h,v 1.3 2003/01/27 21:11:55 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002,2003 Mike Nordell
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-#if BX_USE_PCIVGA_SMF
-# define BX_PCIVGA_THIS thePciVgaAdapter->
-#else
-# define BX_PCIVGA_THIS this->
-#endif
-
-
-class bx_pcivga_c : public bx_devmodel_c
-{
-public:
- bx_pcivga_c(void);
- ~bx_pcivga_c(void);
- virtual void init(void);
- virtual void reset(unsigned type);
-
-private:
-
- struct {
- Bit8u pci_conf[256];
- } s;
-
- static Bit32u pci_read_handler(void *this_ptr, Bit8u address, unsigned io_len);
- static void pci_write_handler(void *this_ptr, Bit8u address, Bit32u value, unsigned io_len);
-#if !BX_USE_PCIVGA_SMF
- Bit32u pci_read(Bit8u address, unsigned io_len);
- void pci_write(Bit8u address, Bit32u value, unsigned io_len);
-#endif
-};
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: pic.cc,v 1.33 2003/08/05 09:19:36 akrisak Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-
-// Define BX_PLUGGABLE in files that can be compiled into plugins. For
-// platforms that require a special tag on exported symbols, BX_PLUGGABLE
-// is used to know when we are exporting symbols and when we are importing.
-#define BX_PLUGGABLE
-
-#include "bochs.h"
-
-#define LOG_THIS thePic->
-
-
-
-bx_pic_c *thePic = NULL;
-
- int
-libpic_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[])
-{
- thePic = new bx_pic_c ();
- bx_devices.pluginPicDevice = thePic;
- BX_REGISTER_DEVICE_DEVMODEL(plugin, type, thePic, BX_PLUGIN_PIC);
- return(0); // Success
-}
-
- void
-libpic_LTX_plugin_fini(void)
-{
-}
-
-
-bx_pic_c::bx_pic_c(void)
-{
- put("PIC");
- settype(PICLOG);
-}
-
-bx_pic_c::~bx_pic_c(void)
-{
- // nothing for now
-}
-
-
- void
-bx_pic_c::init(void)
-{
- /* 8259 PIC (Programmable Interrupt Controller) */
- DEV_register_ioread_handler(this, read_handler, 0x0020, "8259 PIC", 1);
- DEV_register_ioread_handler(this, read_handler, 0x0021, "8259 PIC", 1);
- DEV_register_ioread_handler(this, read_handler, 0x00A0, "8259 PIC", 1);
- DEV_register_ioread_handler(this, read_handler, 0x00A1, "8259 PIC", 1);
-
- DEV_register_iowrite_handler(this, write_handler, 0x0020, "8259 PIC", 1);
- DEV_register_iowrite_handler(this, write_handler, 0x0021, "8259 PIC", 1);
- DEV_register_iowrite_handler(this, write_handler, 0x00A0, "8259 PIC", 1);
- DEV_register_iowrite_handler(this, write_handler, 0x00A1, "8259 PIC", 1);
-
-
- BX_PIC_THIS s.master_pic.single_PIC = 0;
- BX_PIC_THIS s.master_pic.interrupt_offset = 0x08; /* IRQ0 = INT 0x08 */
- /* slave PIC connected to IRQ2 of master */
- BX_PIC_THIS s.master_pic.u.slave_connect_mask = 0x04;
- BX_PIC_THIS s.master_pic.sfnm = 0; /* normal nested mode */
- BX_PIC_THIS s.master_pic.buffered_mode = 0; /* unbuffered mode */
- BX_PIC_THIS s.master_pic.master_slave = 0; /* no meaning, buffered_mode=0 */
- BX_PIC_THIS s.master_pic.auto_eoi = 0; /* manual EOI from CPU */
- BX_PIC_THIS s.master_pic.imr = 0xFF; /* all IRQ's initially masked */
- BX_PIC_THIS s.master_pic.isr = 0x00; /* no IRQ's in service */
- BX_PIC_THIS s.master_pic.irr = 0x00; /* no IRQ's requested */
- BX_PIC_THIS s.master_pic.read_reg_select = 0; /* IRR */
- BX_PIC_THIS s.master_pic.irq = 0;
- BX_PIC_THIS s.master_pic.INT = 0;
- BX_PIC_THIS s.master_pic.init.in_init = 0;
- BX_PIC_THIS s.master_pic.init.requires_4 = 0;
- BX_PIC_THIS s.master_pic.init.byte_expected = 0;
- BX_PIC_THIS s.master_pic.special_mask = 0;
- BX_PIC_THIS s.master_pic.lowest_priority = 7;
- BX_PIC_THIS s.master_pic.polled = 0;
- BX_PIC_THIS s.master_pic.rotate_on_autoeoi = 0;
-
- BX_PIC_THIS s.slave_pic.single_PIC = 0;
- BX_PIC_THIS s.slave_pic.interrupt_offset = 0x70; /* IRQ8 = INT 0x70 */
- BX_PIC_THIS s.slave_pic.u.slave_id = 0x02; /* slave PIC connected to IRQ2 of master */
- BX_PIC_THIS s.slave_pic.sfnm = 0; /* normal nested mode */
- BX_PIC_THIS s.slave_pic.buffered_mode = 0; /* unbuffered mode */
- BX_PIC_THIS s.slave_pic.master_slave = 0; /* no meaning, buffered_mode=0 */
- BX_PIC_THIS s.slave_pic.auto_eoi = 0; /* manual EOI from CPU */
- BX_PIC_THIS s.slave_pic.imr = 0xFF; /* all IRQ's initially masked */
- BX_PIC_THIS s.slave_pic.isr = 0x00; /* no IRQ's in service */
- BX_PIC_THIS s.slave_pic.irr = 0x00; /* no IRQ's requested */
- BX_PIC_THIS s.slave_pic.read_reg_select = 0; /* IRR */
- BX_PIC_THIS s.slave_pic.irq = 0;
- BX_PIC_THIS s.slave_pic.INT = 0;
- BX_PIC_THIS s.slave_pic.init.in_init = 0;
- BX_PIC_THIS s.slave_pic.init.requires_4 = 0;
- BX_PIC_THIS s.slave_pic.init.byte_expected = 0;
- BX_PIC_THIS s.slave_pic.special_mask = 0;
- BX_PIC_THIS s.slave_pic.lowest_priority = 7;
- BX_PIC_THIS s.slave_pic.polled = 0;
- BX_PIC_THIS s.slave_pic.rotate_on_autoeoi = 0;
-
- for (unsigned i=0; i<8; i++) { /* all IRQ lines low */
- BX_PIC_THIS s.master_pic.IRQ_line[i] = 0;
- BX_PIC_THIS s.slave_pic.IRQ_line[i] = 0;
- }
-}
-
- void
-bx_pic_c::reset(unsigned type)
-{
-}
-
- // static IO port read callback handler
- // redirects to non-static class handler to avoid virtual functions
-
- Bit32u
-bx_pic_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len)
-{
-#if !BX_USE_PIC_SMF
- bx_pic_c *class_ptr = (bx_pic_c *) this_ptr;
-
- return( class_ptr->read(address, io_len) );
-}
-
-
-
- Bit32u
-bx_pic_c::read(Bit32u address, unsigned io_len)
-{
-#else
- UNUSED(this_ptr);
-#endif // !BX_USE_PIC_SMF
-
- BX_DEBUG(("IO read from %04x", (unsigned) address));
-
- /*
- 8259A PIC
- */
-
- if((address == 0x20 || address == 0x21) && BX_PIC_THIS s.master_pic.polled) {
- // In polled mode. Treat this as an interrupt acknowledge
- clear_highest_interrupt(& BX_PIC_THIS s.master_pic);
- BX_PIC_THIS s.master_pic.polled = 0;
- service_master_pic();
- return io_len==1?BX_PIC_THIS s.master_pic.irq:(BX_PIC_THIS s.master_pic.irq)<<8|(BX_PIC_THIS s.master_pic.irq); // Return the current irq requested
- }
-
- if((address == 0xa0 || address == 0xa1) && BX_PIC_THIS s.slave_pic.polled) {
- // In polled mode. Treat this as an interrupt acknowledge
- clear_highest_interrupt(& BX_PIC_THIS s.slave_pic);
- BX_PIC_THIS s.slave_pic.polled = 0;
- service_slave_pic();
- return io_len==1?BX_PIC_THIS s.slave_pic.irq:(BX_PIC_THIS s.slave_pic.irq)<<8|(BX_PIC_THIS s.slave_pic.irq); // Return the current irq requested
- }
-
-
- switch (address) {
- case 0x20:
- if (BX_PIC_THIS s.master_pic.read_reg_select) { /* ISR */
- BX_DEBUG(("read master ISR = %02x",
- (unsigned) BX_PIC_THIS s.master_pic.isr));
- return(BX_PIC_THIS s.master_pic.isr);
- }
- else { /* IRR */
- BX_DEBUG(("read master IRR = %02x",
- (unsigned) BX_PIC_THIS s.master_pic.irr));
- return(BX_PIC_THIS s.master_pic.irr);
- }
- break;
- case 0x21:
- BX_DEBUG(("read master IMR = %02x",
- (unsigned) BX_PIC_THIS s.master_pic.imr));
- return(BX_PIC_THIS s.master_pic.imr);
- break;
- case 0xA0:
- if (BX_PIC_THIS s.slave_pic.read_reg_select) { /* ISR */
- BX_DEBUG(("read slave ISR = %02x",
- (unsigned) BX_PIC_THIS s.slave_pic.isr));
- return(BX_PIC_THIS s.slave_pic.isr);
- }
- else { /* IRR */
- BX_DEBUG(("read slave IRR = %02x",
- (unsigned) BX_PIC_THIS s.slave_pic.irr));
- return(BX_PIC_THIS s.slave_pic.irr);
- }
- break;
- case 0xA1:
- BX_DEBUG(("read slave IMR = %02x",
- (unsigned) BX_PIC_THIS s.slave_pic.imr));
- return(BX_PIC_THIS s.slave_pic.imr);
- break;
- }
-
- BX_PANIC(("io read to address %04x", (unsigned) address));
- return(0); /* default if not found above */
-}
-
-
- // static IO port write callback handler
- // redirects to non-static class handler to avoid virtual functions
-
- void
-bx_pic_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len)
-{
-#if !BX_USE_PIC_SMF
- bx_pic_c *class_ptr = (bx_pic_c *) this_ptr;
-
- class_ptr->write(address, value, io_len);
-}
-
- void
-bx_pic_c::write(Bit32u address, Bit32u value, unsigned io_len)
-{
-#else
- UNUSED(this_ptr);
-#endif // !BX_USE_PIC_SMF
-
- BX_DEBUG(("IO write to %04x = %02x", (unsigned) address, (unsigned) value));
-
- /*
- 8259A PIC
- */
-
- switch (address) {
- case 0x20:
- if (value & 0x10) { /* initialization command 1 */
- BX_DEBUG(("master: init command 1 found"));
- BX_DEBUG((" requires 4 = %u", (unsigned) (value & 0x01) ));
- BX_DEBUG((" cascade mode: [0=cascade,1=single] %u",
- (unsigned) ((value & 0x02) >> 1)));
- BX_PIC_THIS s.master_pic.init.in_init = 1;
- BX_PIC_THIS s.master_pic.init.requires_4 = (value & 0x01);
- BX_PIC_THIS s.master_pic.init.byte_expected = 2; /* operation command 2 */
- BX_PIC_THIS s.master_pic.imr = 0x00; /* clear the irq mask register */
- BX_PIC_THIS s.master_pic.isr = 0x00; /* no IRQ's in service */
- BX_PIC_THIS s.master_pic.irr = 0x00; /* no IRQ's requested */
- BX_PIC_THIS s.master_pic.lowest_priority = 7;
- BX_PIC_THIS s.master_pic.INT = 0; /* reprogramming clears previous INTR request */
- BX_PIC_THIS s.master_pic.auto_eoi = 0;
- BX_PIC_THIS s.master_pic.rotate_on_autoeoi = 0;
- if (value & 0x02)
- BX_PANIC(("master: ICW1: single mode not supported"));
- if (value & 0x08) {
- BX_PANIC(("master: ICW1: level sensitive mode not supported"));
- }
- else {
- BX_DEBUG(("master: ICW1: edge triggered mode selected"));
- }
- BX_SET_INTR(0);
- return;
- }
-
- if ( (value & 0x18) == 0x08 ) { /* OCW3 */
- Bit8u special_mask, poll, read_op;
-
- special_mask = (value & 0x60) >> 5;
- poll = (value & 0x04) >> 2;
- read_op = (value & 0x03);
- if (poll) {
- BX_PIC_THIS s.master_pic.polled = 1;
- return;
- }
- if (read_op == 0x02) /* read IRR */
- BX_PIC_THIS s.master_pic.read_reg_select = 0;
- else if (read_op == 0x03) /* read ISR */
- BX_PIC_THIS s.master_pic.read_reg_select = 1;
- if (special_mask == 0x02) { /* cancel special mask */
- BX_PIC_THIS s.master_pic.special_mask = 0;
- }
- else if (special_mask == 0x03) { /* set specific mask */
- BX_PIC_THIS s.master_pic.special_mask = 1;
- service_master_pic();
- }
- return;
- }
-
- /* OCW2 */
- switch (value) {
- case 0x00: // Rotate in auto eoi mode clear
- case 0x80: // Rotate in auto eoi mode set
- BX_PIC_THIS s.master_pic.rotate_on_autoeoi = (value != 0);
- break;
- case 0x0A: /* select read interrupt request register */
- BX_PIC_THIS s.master_pic.read_reg_select = 0;
- break;
- case 0x0B: /* select read interrupt in-service register */
- BX_PIC_THIS s.master_pic.read_reg_select = 1;
- break;
-
- case 0xA0: // Rotate on non-specific end of interrupt
- case 0x20: /* end of interrupt command */
-
- clear_highest_interrupt(& BX_PIC_THIS s.master_pic);
-
- if(value == 0xA0) {// Rotate in Auto-EOI mode
- BX_PIC_THIS s.master_pic.lowest_priority ++;
- if(BX_PIC_THIS s.master_pic.lowest_priority > 7)
- BX_PIC_THIS s.master_pic.lowest_priority = 0;
- }
-
- service_master_pic();
- break;
-
- case 0x40: // Intel PIC spec-sheet seems to indicate this should be ignored
- BX_INFO(("IRQ no-op"));
- break;
-
- case 0x60: /* specific EOI 0 */
- case 0x61: /* specific EOI 1 */
- case 0x62: /* specific EOI 2 */
- case 0x63: /* specific EOI 3 */
- case 0x64: /* specific EOI 4 */
- case 0x65: /* specific EOI 5 */
- case 0x66: /* specific EOI 6 */
- case 0x67: /* specific EOI 7 */
- BX_PIC_THIS s.master_pic.isr &= ~(1 << (value-0x60));
- service_master_pic();
- break;
-
- // IRQ lowest priority commands
- case 0xC0: // 0 7 6 5 4 3 2 1
- case 0xC1: // 1 0 7 6 5 4 3 2
- case 0xC2: // 2 1 0 7 6 5 4 3
- case 0xC3: // 3 2 1 0 7 6 5 4
- case 0xC4: // 4 3 2 1 0 7 6 5
- case 0xC5: // 5 4 3 2 1 0 7 6
- case 0xC6: // 6 5 4 3 2 1 0 7
- case 0xC7: // 7 6 5 4 3 2 1 0
- BX_INFO(("IRQ lowest command 0x%x", value));
- BX_PIC_THIS s.master_pic.lowest_priority = value - 0xC0;
- break;
-
- case 0xE0: // specific EOI and rotate 0
- case 0xE1: // specific EOI and rotate 1
- case 0xE2: // specific EOI and rotate 2
- case 0xE3: // specific EOI and rotate 3
- case 0xE4: // specific EOI and rotate 4
- case 0xE5: // specific EOI and rotate 5
- case 0xE6: // specific EOI and rotate 6
- case 0xE7: // specific EOI and rotate 7
- BX_PIC_THIS s.master_pic.isr &= ~(1 << (value-0xE0));
- BX_PIC_THIS s.master_pic.lowest_priority = (value - 0xE0);
- service_master_pic();
-
- break;
-
- default:
- BX_PANIC(("write to port 20h = %02x", value));
- } /* switch (value) */
- break;
-
- case 0x21:
- /* initialization mode operation */
- if (BX_PIC_THIS s.master_pic.init.in_init) {
- switch (BX_PIC_THIS s.master_pic.init.byte_expected) {
- case 2:
- BX_PIC_THIS s.master_pic.interrupt_offset = value & 0xf8;
- BX_PIC_THIS s.master_pic.init.byte_expected = 3;
- BX_DEBUG(("master: init command 2 = %02x", (unsigned) value));
- BX_DEBUG((" offset = INT %02x",
- BX_PIC_THIS s.master_pic.interrupt_offset));
- return;
- break;
- case 3:
- BX_DEBUG(("master: init command 3 = %02x", (unsigned) value));
- if (BX_PIC_THIS s.master_pic.init.requires_4) {
- BX_PIC_THIS s.master_pic.init.byte_expected = 4;
- }
- else {
- BX_PIC_THIS s.master_pic.init.in_init = 0;
- }
- return;
- break;
- case 4:
- BX_DEBUG(("master: init command 4 = %02x", (unsigned) value));
- if (value & 0x02) {
- BX_DEBUG((" auto EOI"));
- BX_PIC_THIS s.master_pic.auto_eoi = 1;
- }
- else {
- BX_DEBUG(("normal EOI interrupt"));
- BX_PIC_THIS s.master_pic.auto_eoi = 0;
- }
- if (value & 0x01) {
- BX_DEBUG((" 80x86 mode"));
- } else
- BX_PANIC((" not 80x86 mode"));
- BX_PIC_THIS s.master_pic.init.in_init = 0;
- return;
- break;
- default:
- BX_PANIC(("master expecting bad init command"));
- }
- }
-
- /* normal operation */
- BX_DEBUG(("setting master pic IMR to %02x", value));
- BX_PIC_THIS s.master_pic.imr = value;
- service_master_pic();
- return;
- break;
-
- case 0xA0:
- if (value & 0x10) { /* initialization command 1 */
- BX_DEBUG(("slave: init command 1 found"));
- BX_DEBUG((" requires 4 = %u",
- (unsigned) (value & 0x01) ));
- BX_DEBUG((" cascade mode: [0=cascade,1=single] %u",
- (unsigned) ((value & 0x02) >> 1)));
- BX_PIC_THIS s.slave_pic.init.in_init = 1;
- BX_PIC_THIS s.slave_pic.init.requires_4 = (value & 0x01);
- BX_PIC_THIS s.slave_pic.init.byte_expected = 2; /* operation command 2 */
- BX_PIC_THIS s.slave_pic.imr = 0x00; /* clear irq mask */
- BX_PIC_THIS s.slave_pic.isr = 0x00; /* no IRQ's in service */
- BX_PIC_THIS s.slave_pic.irr = 0x00; /* no IRQ's requested */
- BX_PIC_THIS s.slave_pic.lowest_priority = 7;
- BX_PIC_THIS s.slave_pic.INT = 0; /* reprogramming clears previous INTR request */
- BX_PIC_THIS s.slave_pic.auto_eoi = 0;
- BX_PIC_THIS s.slave_pic.rotate_on_autoeoi = 0;
- if (value & 0x02)
- BX_PANIC(("slave: ICW1: single mode not supported"));
- if (value & 0x08) {
- BX_PANIC(("slave: ICW1: level sensitive mode not supported"));
- }
- else {
- BX_DEBUG(("slave: ICW1: edge triggered mode selected"));
- }
- return;
- }
-
- if ( (value & 0x18) == 0x08 ) { /* OCW3 */
- Bit8u special_mask, poll, read_op;
-
- special_mask = (value & 0x60) >> 5;
- poll = (value & 0x04) >> 2;
- read_op = (value & 0x03);
- if (poll) {
- BX_PIC_THIS s.slave_pic.polled = 1;
- return;
- }
- if (read_op == 0x02) /* read IRR */
- BX_PIC_THIS s.slave_pic.read_reg_select = 0;
- else if (read_op == 0x03) /* read ISR */
- BX_PIC_THIS s.slave_pic.read_reg_select = 1;
- if (special_mask == 0x02) { /* cancel special mask */
- BX_PIC_THIS s.slave_pic.special_mask = 0;
- }
- else if (special_mask == 0x03) { /* set specific mask */
- BX_PIC_THIS s.slave_pic.special_mask = 1;
- service_slave_pic();
- }
- return;
- }
-
- switch (value) {
- case 0x00: // Rotate in auto eoi mode clear
- case 0x80: // Rotate in auto eoi mode set
- BX_PIC_THIS s.slave_pic.rotate_on_autoeoi = (value != 0);
- break;
-
- case 0x0A: /* select read interrupt request register */
- BX_PIC_THIS s.slave_pic.read_reg_select = 0;
- break;
- case 0x0B: /* select read interrupt in-service register */
- BX_PIC_THIS s.slave_pic.read_reg_select = 1;
- break;
-
- case 0xA0: // Rotate on non-specific end of interrupt
- case 0x20: /* end of interrupt command */
-
- clear_highest_interrupt(& BX_PIC_THIS s.slave_pic);
-
- if(value == 0xA0) {// Rotate in Auto-EOI mode
- BX_PIC_THIS s.slave_pic.lowest_priority ++;
- if(BX_PIC_THIS s.slave_pic.lowest_priority > 7)
- BX_PIC_THIS s.slave_pic.lowest_priority = 0;
- }
-
- service_slave_pic();
- break;
-
- case 0x40: // Intel PIC spec-sheet seems to indicate this should be ignored
- BX_INFO(("IRQ no-op"));
- break;
-
- case 0x60: /* specific EOI 0 */
- case 0x61: /* specific EOI 1 */
- case 0x62: /* specific EOI 2 */
- case 0x63: /* specific EOI 3 */
- case 0x64: /* specific EOI 4 */
- case 0x65: /* specific EOI 5 */
- case 0x66: /* specific EOI 6 */
- case 0x67: /* specific EOI 7 */
- BX_PIC_THIS s.slave_pic.isr &= ~(1 << (value-0x60));
- service_slave_pic();
- break;
-
- // IRQ lowest priority commands
- case 0xC0: // 0 7 6 5 4 3 2 1
- case 0xC1: // 1 0 7 6 5 4 3 2
- case 0xC2: // 2 1 0 7 6 5 4 3
- case 0xC3: // 3 2 1 0 7 6 5 4
- case 0xC4: // 4 3 2 1 0 7 6 5
- case 0xC5: // 5 4 3 2 1 0 7 6
- case 0xC6: // 6 5 4 3 2 1 0 7
- case 0xC7: // 7 6 5 4 3 2 1 0
- BX_INFO(("IRQ lowest command 0x%x", value));
- BX_PIC_THIS s.slave_pic.lowest_priority = value - 0xC0;
- break;
-
- case 0xE0: // specific EOI and rotate 0
- case 0xE1: // specific EOI and rotate 1
- case 0xE2: // specific EOI and rotate 2
- case 0xE3: // specific EOI and rotate 3
- case 0xE4: // specific EOI and rotate 4
- case 0xE5: // specific EOI and rotate 5
- case 0xE6: // specific EOI and rotate 6
- case 0xE7: // specific EOI and rotate 7
- BX_PIC_THIS s.slave_pic.isr &= ~(1 << (value-0xE0));
- BX_PIC_THIS s.slave_pic.lowest_priority = (value - 0xE0);
- service_slave_pic();
-
- break;
-
- default:
- BX_PANIC(("write to port A0h = %02x", value));
- } /* switch (value) */
- break;
-
- case 0xA1:
- /* initialization mode operation */
- if (BX_PIC_THIS s.slave_pic.init.in_init) {
- switch (BX_PIC_THIS s.slave_pic.init.byte_expected) {
- case 2:
- BX_PIC_THIS s.slave_pic.interrupt_offset = value & 0xf8;
- BX_PIC_THIS s.slave_pic.init.byte_expected = 3;
- BX_DEBUG(("slave: init command 2 = %02x", (unsigned) value));
- BX_DEBUG((" offset = INT %02x",
- BX_PIC_THIS s.slave_pic.interrupt_offset));
- return;
- break;
- case 3:
- BX_DEBUG(("slave: init command 3 = %02x", (unsigned) value));
- if (BX_PIC_THIS s.slave_pic.init.requires_4) {
- BX_PIC_THIS s.slave_pic.init.byte_expected = 4;
- } else {
- BX_PIC_THIS s.slave_pic.init.in_init = 0;
- }
- return;
- break;
- case 4:
- BX_DEBUG(("slave: init command 4 = %02x", (unsigned) value));
- if (value & 0x02) {
- BX_DEBUG((" auto EOI"));
- BX_PIC_THIS s.slave_pic.auto_eoi = 1;
- }
- else {
- BX_DEBUG(("normal EOI interrupt"));
- BX_PIC_THIS s.slave_pic.auto_eoi = 0;
- }
- if (value & 0x01) {
- BX_DEBUG((" 80x86 mode"));
- } else
- BX_PANIC((" not 80x86 mode"));
- BX_PIC_THIS s.slave_pic.init.in_init = 0;
- return;
- break;
- default:
- BX_PANIC(("slave: expecting bad init command"));
- }
- }
-
- /* normal operation */
- BX_DEBUG(("setting slave pic IMR to %02x", value));
- BX_PIC_THIS s.slave_pic.imr = value;
- service_slave_pic();
- return;
- break;
- } /* switch (address) */
-
- return;
-}
-
-// new IRQ signal handling routines
-
- void
-bx_pic_c::lower_irq(unsigned irq_no)
-{
-#if BX_SUPPORT_APIC
- // forward this function call to the ioapic too
- if (DEV_ioapic_present())
- bx_devices.ioapic->untrigger_irq (irq_no, -1);
-#endif
-
- if ((irq_no <= 7) && (BX_PIC_THIS s.master_pic.IRQ_line[irq_no])) {
- BX_DEBUG(("IRQ line %d now low", (unsigned) irq_no));
- BX_PIC_THIS s.master_pic.IRQ_line[irq_no] = 0;
- BX_PIC_THIS s.master_pic.irr &= ~(1 << irq_no);
- if ((BX_PIC_THIS s.master_pic.irr & ~BX_PIC_THIS s.master_pic.imr) == 0) {
- BX_SET_INTR(0);
- BX_PIC_THIS s.master_pic.INT = 0;
- }
- } else if ((irq_no > 7) && (irq_no <= 15) &&
- (BX_PIC_THIS s.slave_pic.IRQ_line[irq_no-8])) {
- BX_DEBUG(("IRQ line %d now low", (unsigned) irq_no));
- BX_PIC_THIS s.slave_pic.IRQ_line[irq_no - 8] = 0;
- BX_PIC_THIS s.slave_pic.irr &= ~(1 << (irq_no - 8));
- if ((BX_PIC_THIS s.slave_pic.irr & ~BX_PIC_THIS s.slave_pic.imr) == 0) {
- BX_PIC_THIS s.slave_pic.INT = 0;
- lower_irq(2);
- }
- }
-}
-
- void
-bx_pic_c::raise_irq(unsigned irq_no)
-{
-#if BX_SUPPORT_APIC
- // forward this function call to the ioapic too
- bx_devices.ioapic->trigger_irq (irq_no, -1);
-#endif
-
- if ((irq_no <= 7) && (!BX_PIC_THIS s.master_pic.IRQ_line[irq_no])) {
- BX_DEBUG(("IRQ line %d now high", (unsigned) irq_no));
- BX_PIC_THIS s.master_pic.IRQ_line[irq_no] = 1;
- BX_PIC_THIS s.master_pic.irr |= (1 << irq_no);
- service_master_pic();
- } else if ((irq_no > 7) && (irq_no <= 15) &&
- (!BX_PIC_THIS s.slave_pic.IRQ_line[irq_no-8])) {
- BX_DEBUG(("IRQ line %d now high", (unsigned) irq_no));
- BX_PIC_THIS s.slave_pic.IRQ_line[irq_no - 8] = 1;
- BX_PIC_THIS s.slave_pic.irr |= (1 << (irq_no - 8));
- service_slave_pic();
- }
-}
-
-void bx_pic_c::clear_highest_interrupt(bx_pic_t *pic)
-{
- int irq;
- int lowest_priority;
- int highest_priority;
-
- /* clear highest current in service bit */
- lowest_priority = pic->lowest_priority;
- highest_priority = lowest_priority + 1;
- if(highest_priority > 7)
- highest_priority = 0;
-
- irq = highest_priority;
- do {
- if (pic->isr & (1 << irq)) {
- pic->isr &= ~(1 << irq);
- break; /* Return mask of bit cleared. */
- }
-
- irq ++;
- if(irq > 7)
- irq = 0;
- } while(irq != highest_priority);
-
-}
-
- /* */
- void
-bx_pic_c::service_master_pic(void)
-{
- Bit8u unmasked_requests;
- int irq;
- Bit8u isr, max_irq;
- Bit8u highest_priority = BX_PIC_THIS s.master_pic.lowest_priority + 1;
- if(highest_priority > 7)
- highest_priority = 0;
-
- if (BX_PIC_THIS s.master_pic.INT) { /* last interrupt still not acknowleged */
- return;
- }
-
- if (BX_PIC_THIS s.master_pic.special_mask) {
- /* all priorities may be enabled. check all IRR bits except ones
- * which have corresponding ISR bits set
- */
- max_irq = highest_priority;
- }
- else { /* normal mode */
- /* Find the highest priority IRQ that is enabled due to current ISR */
- isr = BX_PIC_THIS s.master_pic.isr;
- if (isr) {
- max_irq = highest_priority;
- while ( (isr & (1 << max_irq)) == 0) {
- max_irq++;
- if(max_irq > 7)
- max_irq = 0;
- }
- if (max_irq == highest_priority ) return; /* Highest priority interrupt in-service,
- * no other priorities allowed */
- if (max_irq > 7) BX_PANIC(("error in service_master_pic()"));
- }
- else
- max_irq = highest_priority; /* 0..7 bits in ISR are cleared */
- }
-
-
- /* now, see if there are any higher priority requests */
- if ((unmasked_requests = (BX_PIC_THIS s.master_pic.irr & ~BX_PIC_THIS s.master_pic.imr)) ) {
- irq = highest_priority;
- do {
- /* for special mode, since we're looking at all IRQ's, skip if
- * current IRQ is already in-service
- */
- if ( ! (BX_PIC_THIS s.master_pic.special_mask && ((BX_PIC_THIS s.master_pic.isr >> irq) & 0x01)) ) {
- if (unmasked_requests & (1 << irq)) {
- BX_DEBUG(("signalling IRQ(%u)", (unsigned) irq));
- BX_PIC_THIS s.master_pic.INT = 1;
- BX_SET_INTR(1);
- BX_PIC_THIS s.master_pic.irq = irq;
- return;
- } /* if (unmasked_requests & ... */
- }
-
- irq ++;
- if(irq > 7)
- irq = 0;
- } while(irq != max_irq); /* do ... */
- } /* if (unmasked_requests = ... */
-}
-
-
- void
-bx_pic_c::service_slave_pic(void)
-{
- Bit8u unmasked_requests;
- int irq;
- Bit8u isr, max_irq;
- Bit8u highest_priority = BX_PIC_THIS s.slave_pic.lowest_priority + 1;
- if(highest_priority > 7)
- highest_priority = 0;
-
- if (BX_PIC_THIS s.slave_pic.INT) { /* last interrupt still not acknowleged */
- return;
- }
-
- if (BX_PIC_THIS s.slave_pic.special_mask) {
- /* all priorities may be enabled. check all IRR bits except ones
- * which have corresponding ISR bits set
- */
- max_irq = highest_priority;
- }
- else { /* normal mode */
- /* Find the highest priority IRQ that is enabled due to current ISR */
- isr = BX_PIC_THIS s.slave_pic.isr;
- if (isr) {
- max_irq = highest_priority;
- while ( (isr & (1 << max_irq)) == 0) {
- max_irq++;
- if(max_irq > 7)
- max_irq = 0;
- }
- if (max_irq == highest_priority ) return; /* Highest priority interrupt in-service,
- * no other priorities allowed */
- if (max_irq > 7) BX_PANIC(("error in service_master_pic()"));
- }
- else
- max_irq = highest_priority; /* 0..7 bits in ISR are cleared */
- }
-
-
- /* now, see if there are any higher priority requests */
- if ((unmasked_requests = (BX_PIC_THIS s.slave_pic.irr & ~BX_PIC_THIS s.slave_pic.imr)) ) {
- irq = highest_priority;
- do {
- /* for special mode, since we're looking at all IRQ's, skip if
- * current IRQ is already in-service
- */
- if ( ! (BX_PIC_THIS s.slave_pic.special_mask && ((BX_PIC_THIS s.slave_pic.isr >> irq) & 0x01)) ) {
- if (unmasked_requests & (1 << irq)) {
- BX_DEBUG(("slave: signalling IRQ(%u)", (unsigned) 8 + irq));
-
- BX_PIC_THIS s.slave_pic.INT = 1;
- BX_PIC_THIS s.slave_pic.irq = irq;
- BX_PIC_THIS raise_irq(2); /* request IRQ 2 on master pic */
- return;
- } /* if (unmasked_requests & ... */
- }
-
- irq ++;
- if(irq > 7)
- irq = 0;
- } while(irq != max_irq); /* do ... */
- } /* if (unmasked_requests = ... */
-}
-
-
- /* CPU handshakes with PIC after acknowledging interrupt */
- Bit8u
-bx_pic_c::IAC(void)
-{
- Bit8u vector;
- Bit8u irq;
-
- BX_SET_INTR(0);
- BX_PIC_THIS s.master_pic.INT = 0;
- BX_PIC_THIS s.master_pic.irr &= ~(1 << BX_PIC_THIS s.master_pic.irq);
- // In autoeoi mode don't set the isr bit.
- if(!BX_PIC_THIS s.master_pic.auto_eoi)
- BX_PIC_THIS s.master_pic.isr |= (1 << BX_PIC_THIS s.master_pic.irq);
- else if(BX_PIC_THIS s.master_pic.rotate_on_autoeoi)
- BX_PIC_THIS s.master_pic.lowest_priority = BX_PIC_THIS s.master_pic.irq;
-
- if (BX_PIC_THIS s.master_pic.irq != 2) {
- irq = BX_PIC_THIS s.master_pic.irq;
- vector = irq + BX_PIC_THIS s.master_pic.interrupt_offset;
- }
- else { /* IRQ2 = slave pic IRQ8..15 */
- BX_PIC_THIS s.slave_pic.INT = 0;
- BX_PIC_THIS s.master_pic.IRQ_line[2] = 0;
- irq = BX_PIC_THIS s.slave_pic.irq;
- vector = irq + BX_PIC_THIS s.slave_pic.interrupt_offset;
- BX_PIC_THIS s.slave_pic.irr &= ~(1 << BX_PIC_THIS s.slave_pic.irq);
- // In autoeoi mode don't set the isr bit.
- if(!BX_PIC_THIS s.slave_pic.auto_eoi)
- BX_PIC_THIS s.slave_pic.isr |= (1 << BX_PIC_THIS s.slave_pic.irq);
- else if(BX_PIC_THIS s.slave_pic.rotate_on_autoeoi)
- BX_PIC_THIS s.slave_pic.lowest_priority = BX_PIC_THIS s.slave_pic.irq;
- service_slave_pic();
- irq += 8; // for debug printing purposes
- }
-
- service_master_pic();
-
- BX_DBG_IAC_REPORT(vector, irq);
- return(vector);
-}
-
- Bit8u
-bx_pic_c::irq_to_vec(Bit8u irq)
-{
- Bit8u vector = 0;
-
- if (irq >= 8 && irq <= 15)
- vector = irq + BX_PIC_THIS s.slave_pic.interrupt_offset;
- else if (irq != 2 && irq <= 7)
- vector = irq + BX_PIC_THIS s.master_pic.interrupt_offset;
- else
- BX_ERROR(("invalid irq!\n"));
-
- return vector;
-}
-
- void
-bx_pic_c::show_pic_state(void)
-{
-#if defined(BX_DEBUGGER) && (BX_DEBUGGER == 1)
-dbg_printf("s.master_pic.imr = %02x\n", BX_PIC_THIS s.master_pic.imr);
-dbg_printf("s.master_pic.isr = %02x\n", BX_PIC_THIS s.master_pic.isr);
-dbg_printf("s.master_pic.irr = %02x\n", BX_PIC_THIS s.master_pic.irr);
-dbg_printf("s.master_pic.irq = %02x\n", BX_PIC_THIS s.master_pic.irq);
-dbg_printf("s.slave_pic.imr = %02x\n", BX_PIC_THIS s.slave_pic.imr);
-dbg_printf("s.slave_pic.isr = %02x\n", BX_PIC_THIS s.slave_pic.isr);
-dbg_printf("s.slave_pic.irr = %02x\n", BX_PIC_THIS s.slave_pic.irr);
-dbg_printf("s.slave_pic.irq = %02x\n", BX_PIC_THIS s.slave_pic.irq);
-#endif
-}
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: pic.h,v 1.11 2003/08/04 16:03:09 akrisak Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-#if BX_USE_PIC_SMF
-# define BX_PIC_SMF static
-# define BX_PIC_THIS thePic->
-#else
-# define BX_PIC_SMF
-# define BX_PIC_THIS this->
-#endif
-
-
-
-typedef struct {
- Bit8u single_PIC; /* 0=cascaded PIC, 1=master only */
- Bit8u interrupt_offset; /* programmable interrupt vector offset */
- union {
- Bit8u slave_connect_mask; /* for master, a bit for each interrupt line
- 0=not connect to a slave, 1=connected */
- Bit8u slave_id; /* for slave, id number of slave PIC */
- } u;
- Bit8u sfnm; /* specially fully nested mode: 0=no, 1=yes*/
- Bit8u buffered_mode; /* 0=no buffered mode, 1=buffered mode */
- Bit8u master_slave; /* master/slave: 0=slave PIC, 1=master PIC */
- Bit8u auto_eoi; /* 0=manual EOI, 1=automatic EOI */
- Bit8u imr; /* interrupt mask register, 1=masked */
- Bit8u isr; /* in service register */
- Bit8u irr; /* interrupt request register */
- Bit8u read_reg_select; /* 0=IRR, 1=ISR */
- Bit8u irq; /* current IRQ number */
- Bit8u lowest_priority; /* current lowest priority irq */
- bx_bool INT; /* INT request pin of PIC */
- bx_bool IRQ_line[8]; /* IRQ pins of PIC */
- struct {
- bx_bool in_init;
- bx_bool requires_4;
- int byte_expected;
- } init;
- bx_bool special_mask;
- bx_bool polled; /* Set when poll command is issued. */
- bx_bool rotate_on_autoeoi; /* Set when should rotate in auto-eoi mode. */
- } bx_pic_t;
-
-
-class bx_pic_c : public bx_pic_stub_c {
-public:
- bx_pic_c(void);
- ~bx_pic_c(void);
- virtual void init(void);
- virtual void reset(unsigned type);
- virtual void lower_irq(unsigned irq_no);
- virtual void raise_irq(unsigned irq_no);
- virtual Bit8u IAC(void);
- virtual void show_pic_state(void);
- Bit8u irq_to_vec(Bit8u);
-
-private:
- struct {
- bx_pic_t master_pic;
- bx_pic_t slave_pic;
- } s;
-
- static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len);
- static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len);
-#if !BX_USE_PIC_SMF
- Bit32u read(Bit32u address, unsigned io_len);
- void write(Bit32u address, Bit32u value, unsigned io_len);
-#endif
-
- BX_PIC_SMF void service_master_pic(void);
- BX_PIC_SMF void service_slave_pic(void);
- BX_PIC_SMF void clear_highest_interrupt(bx_pic_t *pic);
- };
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: pit.cc,v 1.15 2003/07/31 12:04:48 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2001 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-
-#include "bochs.h"
-
-#if (BX_USE_NEW_PIT==0)
-
-#define LOG_THIS bx_pit.
-
-
-// NOTES ON THE 8253/8254 PIT MODES
-
-// MODE 0: Interrupt on Terminal Count
-// ===================================
-// Writing new count action:
-// loaded upon next CLK pulse. counting doesn't start until GATE=1
-// GATE 0..1 transition:
-// ???
-// GATE 1..0 transition:
-// counter expiration action:
-// wraps to FFFF
-// * OUT rises until new count val or new control word for mode 0 written
-
-// MODE 1: Programmable Monoflop
-// =============================
-// Writing new count action:
-// not effective for current process
-// GATE 0..1 transition:
-// loads counter
-// counter expiration action:
-// wraps to FFFF
-// NOTES:
-// OUT rises until new count val or new control word for mode 0 written
-
-// MODE 2: Rate Generator
-// ======================
-// Writing new count action:
-// ???
-// GATE 0..1 transition:
-// loads initial count val and starts counting
-// counter expiration action:
-// reloads after count expires
-// NOTES:
-// * after control word & initial count val N loaded, PIT starts
-// counting upon next CLK pulse.
-// * when counter reaches 1, OUT drops to a low level, for one
-// CLK cycle. (short peak pulse generated)
-// * afterwards, the initial count val is automatically reloaded
-// and the PIT restarts the same counting operation again.
-// * distance of two OUT pulses is N CLK cycles long.
-// * GATE=1 enables, GATE=0 disables counter.
-// * if GATE drops to low level during counting operation and rises
-// to high level later, PIT loads initial count value at the
-// rise and starts counting.
-// * PIT starts counting after last data byte written if GATE=1
-// * if the output is low when the gate goes low, the output is
-// immediately set high.
-
-// MODE 3: Square Wave Generator
-// =============================
-// Writing new count action:
-// ???
-// GATE 0..1 transition:
-// ???
-// counter expiration action:
-// reloads after count expires
-// NOTES:
-// * initially OUT at a high level
-// * drop of GATE to a low level while OUT low, raises OUT to a high level
-// * a rise from a low to a high level at GATE (trigger pulse),
-// loads the counter with the initial count value and starts
-// counting operation
-// * a new count value supplied during the course of an active
-// counting operation doesn't affect the current process.
-// At the end of the current half cycle, the PIT loads the new value
-// * if the GATE line goes low, count is temporarily halted until GATE
-// returns high
-// * if the OUT line is high when GATE goes low, OUT is forced low.
-// ??? different for odd/even counts
-
-// MODE 4: Software Triggered Pulse
-// ================================
-// Writing new count action:
-// ???
-// GATE 0..1 transition:
-// ???
-// counter expiration action:
-// wraps to FFFF
-// NOTES:
-
-// MODE 5: Hardware Triggered Pulse
-// ================================
-// Writing new count action:
-// ???
-// GATE 0..1 transition:
-// ???
-// counter expiration action:
-// wraps to FFFF
-// NOTES:
-
-
-
-#define BX_PIT_LATCH_MODE_LSB 10
-#define BX_PIT_LATCH_MODE_MSB 11
-#define BX_PIT_LATCH_MODE_16BIT 12
-
-
-bx_pit_c bx_pit;
-#if BX_USE_PIT_SMF
-#define this (&bx_pit)
-#endif
-
-#ifdef OUT
-# undef OUT
-#endif
-
-
-bx_pit_c::bx_pit_c( void )
-{
- put("PIT");
- settype(PITLOG);
- memset(&s, 0, sizeof(s));
-
- /* 8254 PIT (Programmable Interval Timer) */
-
- BX_PIT_THIS s.timer_handle[1] = BX_NULL_TIMER_HANDLE;
- BX_PIT_THIS s.timer_handle[2] = BX_NULL_TIMER_HANDLE;
-}
-
-bx_pit_c::~bx_pit_c( void )
-{
-}
-
-
- int
-bx_pit_c::init( void )
-{
- DEV_register_irq(0, "8254 PIT");
- DEV_register_ioread_handler(this, read_handler, 0x0040, "8254 PIT", 1);
- DEV_register_ioread_handler(this, read_handler, 0x0041, "8254 PIT", 1);
- DEV_register_ioread_handler(this, read_handler, 0x0042, "8254 PIT", 1);
- DEV_register_ioread_handler(this, read_handler, 0x0043, "8254 PIT", 1);
- DEV_register_ioread_handler(this, read_handler, 0x0061, "8254 PIT", 1);
-
- DEV_register_iowrite_handler(this, write_handler, 0x0040, "8254 PIT", 1);
- DEV_register_iowrite_handler(this, write_handler, 0x0041, "8254 PIT", 1);
- DEV_register_iowrite_handler(this, write_handler, 0x0042, "8254 PIT", 1);
- DEV_register_iowrite_handler(this, write_handler, 0x0043, "8254 PIT", 1);
- DEV_register_iowrite_handler(this, write_handler, 0x0061, "8254 PIT", 1);
-
- BX_PIT_THIS s.speaker_data_on = 0;
- BX_PIT_THIS s.refresh_clock_div2 = 0;
-
- BX_PIT_THIS s.timer[0].mode = 3; /* periodic rate generator */
- BX_PIT_THIS s.timer[0].latch_mode = BX_PIT_LATCH_MODE_16BIT;
- BX_PIT_THIS s.timer[0].input_latch_value = 0;
- BX_PIT_THIS s.timer[0].input_latch_toggle = 0;
- BX_PIT_THIS s.timer[0].output_latch_value = 0;
- BX_PIT_THIS s.timer[0].output_latch_toggle = 0;
- BX_PIT_THIS s.timer[0].output_latch_full = 0;
- BX_PIT_THIS s.timer[0].counter_max = 0; /* 0xFFFF + 1 : (1193182 / 65535 = 18.2Hz) */
- BX_PIT_THIS s.timer[0].counter = 0; /* 0xFFFF + 1 : (1193182 / 65535 = 18.2Hz) */
- BX_PIT_THIS s.timer[0].bcd_mode = 0; /* binary counting mode */
- BX_PIT_THIS s.timer[0].GATE = 1; /* GATE tied to + logic */
- BX_PIT_THIS s.timer[0].OUT = 1;
- BX_PIT_THIS s.timer[0].active = 0;
-
- BX_PIT_THIS s.timer[1].mode = 3; /* periodic rate generator */
- BX_PIT_THIS s.timer[1].latch_mode = BX_PIT_LATCH_MODE_16BIT;
- BX_PIT_THIS s.timer[1].input_latch_value = 0;
- BX_PIT_THIS s.timer[1].input_latch_toggle = 0;
- BX_PIT_THIS s.timer[1].output_latch_value = 0;
- BX_PIT_THIS s.timer[1].output_latch_toggle = 0;
- BX_PIT_THIS s.timer[1].output_latch_full = 0;
- BX_PIT_THIS s.timer[1].counter_max = 0; /* 0xFFFF + 1 : (1193182 / 65535 = 18.2Hz) */
- BX_PIT_THIS s.timer[1].counter = 0; /* 0xFFFF + 1 : (1193182 / 65535 = 18.2Hz) */
- BX_PIT_THIS s.timer[1].bcd_mode = 0; /* binary counting mode */
- BX_PIT_THIS s.timer[1].GATE = 1; /* GATE tied to + logic */
- BX_PIT_THIS s.timer[1].OUT = 1;
- BX_PIT_THIS s.timer[1].active = 0;
-
- BX_PIT_THIS s.timer[2].mode = 3; /* periodic rate generator */
- BX_PIT_THIS s.timer[2].latch_mode = BX_PIT_LATCH_MODE_16BIT;
- BX_PIT_THIS s.timer[2].input_latch_value = 0;
- BX_PIT_THIS s.timer[2].input_latch_toggle = 0;
- BX_PIT_THIS s.timer[2].output_latch_value = 0;
- BX_PIT_THIS s.timer[2].output_latch_toggle = 0;
- BX_PIT_THIS s.timer[2].output_latch_full = 0;
- BX_PIT_THIS s.timer[2].counter_max = 0; /* 0xFFFF + 1 : (1193182 / 65535 = 18.2Hz) */
- BX_PIT_THIS s.timer[2].counter = 0; /* 0xFFFF + 1 : (1193182 / 65535 = 18.2Hz) */
- BX_PIT_THIS s.timer[2].bcd_mode = 0; /* binary counting mode */
- BX_PIT_THIS s.timer[2].GATE = 0; /* timer2 gate controlled by port 61h bit 0 */
- BX_PIT_THIS s.timer[2].OUT = 1;
- BX_PIT_THIS s.timer[2].active = 0;
-
- return(1);
-}
-
-void bx_pit_c::reset(unsigned type) {
-}
-
- // static IO port read callback handler
- // redirects to non-static class handler to avoid virtual functions
-
- Bit32u
-bx_pit_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len)
-{
-#if !BX_USE_PIT_SMF
- bx_pit_c *class_ptr = (bx_pit_c *) this_ptr;
-
- return( class_ptr->read(address, io_len) );
-}
-
-
- Bit32u
-bx_pit_c::read( Bit32u address, unsigned int io_len )
-{
-#else
- UNUSED(this_ptr);
-#endif // !BX_USE_PIT_SMF
- if (bx_dbg.pit)
- BX_INFO(("pit: io read from port %04x", (unsigned) address));
-
- switch (address) {
- case 0x40: /* timer 0 - system ticks */
- return( read_counter(0) );
- break;
-
- case 0x42: /* timer 2 read */
- return( read_counter(2) );
- break;
-
- case 0x61:
- /* AT, port 61h */
- BX_PIT_THIS s.refresh_clock_div2 = !BX_PIT_THIS s.refresh_clock_div2;
- return( (BX_PIT_THIS s.timer[2].OUT<<5) |
- (BX_PIT_THIS s.refresh_clock_div2<<4) |
- (BX_PIT_THIS s.speaker_data_on<<1) |
- (BX_PIT_THIS s.timer[2].GATE) );
- break;
-
- default:
- BX_PANIC(("pit: unsupported io read from port %04x", address));
- }
- return(0); /* keep compiler happy */
-}
-
-
- // static IO port write callback handler
- // redirects to non-static class handler to avoid virtual functions
-
- void
-bx_pit_c::write_handler(void *this_ptr, Bit32u address, Bit32u dvalue, unsigned io_len)
-{
-#if !BX_USE_PIT_SMF
- bx_pit_c *class_ptr = (bx_pit_c *) this_ptr;
-
- class_ptr->write(address, dvalue, io_len);
-}
-
- void
-bx_pit_c::write( Bit32u address, Bit32u dvalue,
- unsigned int io_len )
-{
-#else
- UNUSED(this_ptr);
-#endif // !BX_USE_PIT_SMF
- Bit8u command, mode, bcd_mode;
- Bit8u value;
-
- value = (Bit8u ) dvalue;
-
- if (bx_dbg.pit)
- BX_INFO(("pit: write to port %04x = %02x",
- (unsigned) address, (unsigned) value));
-
- switch (address) {
- case 0x40: /* timer 0: write count register */
- write_count_reg( value, 0 );
- break;
-
- case 0x41: /* timer 1: write count register */
- write_count_reg( value, 1 );
- break;
-
- case 0x42: /* timer 2: write count register */
- write_count_reg( value, 2 );
- break;
-
- case 0x43: /* timer 0-2 mode control */
- /* |7 6 5 4|3 2 1|0|
- * |-------|-----|-|
- * |command|mode |bcd/binary|
- */
- command = value >> 4;
- mode = (value >> 1) & 0x07;
- bcd_mode = value & 0x01;
-#if 0
-BX_INFO(("timer 0-2 mode control: comm:%02x mode:%02x bcd_mode:%u",
- (unsigned) command, (unsigned) mode, (unsigned) bcd_mode));
-#endif
-
- if ( (mode > 5) || (command > 0x0e) )
- BX_PANIC(("pit: outp(43h)=%02xh out of range", (unsigned) value));
- if (bcd_mode)
- BX_PANIC(("pit: outp(43h)=%02xh: bcd mode unhandled",
- (unsigned) bcd_mode));
-
- switch (command) {
- case 0x0: /* timer 0: counter latch */
- latch( 0 );
- break;
-
- case 0x1: /* timer 0: LSB mode */
- case 0x2: /* timer 0: MSB mode */
- BX_PANIC(("pit: outp(43h): command %02xh unhandled",
- (unsigned) command));
- break;
- case 0x3: /* timer 0: 16-bit mode */
- BX_PIT_THIS s.timer[0].mode = mode;
- BX_PIT_THIS s.timer[0].latch_mode = BX_PIT_LATCH_MODE_16BIT;
- BX_PIT_THIS s.timer[0].input_latch_value = 0;
- BX_PIT_THIS s.timer[0].input_latch_toggle = 0;
- BX_PIT_THIS s.timer[0].bcd_mode = bcd_mode;
- if ( (mode!=3 && mode!=2 && mode!=0) || bcd_mode!=0 )
- BX_PANIC(("pit: outp(43h): comm 3, mode %02x, bcd %02x unhandled",
- (unsigned) mode, bcd_mode));
- break;
- case 0x4: /* timer 1: counter latch */
- latch( 1 );
- break;
-
- case 0x5: /* timer 1: LSB mode */
- case 0x6: /* timer 1: MSB mode */
- BX_INFO(("pit: outp(43h): command %02xh unhandled (ignored)",
- (unsigned) command));
- break;
- case 0x7: /* timer 1: 16-bit mode */
- BX_PIT_THIS s.timer[1].mode = mode;
- BX_PIT_THIS s.timer[1].latch_mode = BX_PIT_LATCH_MODE_16BIT;
- BX_PIT_THIS s.timer[1].input_latch_value = 0;
- BX_PIT_THIS s.timer[1].input_latch_toggle = 0;
- BX_PIT_THIS s.timer[1].bcd_mode = bcd_mode;
- if ( (mode!=3 && mode!=2 && mode!=0) || bcd_mode!=0 )
- BX_PANIC(("pit: outp(43h): comm 7, mode %02x, bcd %02x unhandled",
- (unsigned) mode, bcd_mode));
- break;
- case 0x8: /* timer 2: counter latch */
- latch( 2 );
- break;
-
- case 0x9: /* timer 2: LSB mode */
- case 0xa: /* timer 2: MSB mode */
- BX_PANIC(("pit: outp(43h): command %02xh unhandled",
- (unsigned) command));
- break;
- case 0xb: /* timer 2: 16-bit mode */
- BX_PIT_THIS s.timer[2].mode = mode;
- BX_PIT_THIS s.timer[2].latch_mode = BX_PIT_LATCH_MODE_16BIT;
- BX_PIT_THIS s.timer[2].input_latch_value = 0;
- BX_PIT_THIS s.timer[2].input_latch_toggle = 0;
- BX_PIT_THIS s.timer[2].bcd_mode = bcd_mode;
- if ( (mode!=3 && mode!=2 && mode!=0) || bcd_mode!=0 )
- BX_PANIC(("pit: outp(43h): comm Bh, mode %02x, bcd %02x unhandled",
- (unsigned) mode, bcd_mode));
- break;
-#if 0
- case 0xd: /* general counter latch */
- if (value & 0x08) /* select counter 2 */
- latch( 2 );
- if (value & 0x04) /* select counter 1 */
- latch( 1 );
- if (value & 0x02) /* select counter 0 */
- latch( 0 );
- break;
-
- case 0xe: /* latch status of timers */
- BX_PANIC(("pit: outp(43h): command %02xh unhandled",
- (unsigned) command);
- break;
-#endif
- case 0x0c: case 0x0d: case 0x0e: case 0x0f:
- BX_INFO(("pit: ignoring 8254 command %u", (unsigned) command));
- break;
-
- default: /* 0xc & 0xf */
- BX_PANIC(("pit: outp(43h) command %1xh unhandled",
- (unsigned) command));
- break;
- }
- break;
-
- case 0x61:
- BX_PIT_THIS s.speaker_data_on = (value >> 1) & 0x01;
-/*??? only on AT+ */
- set_GATE(2, value & 0x01);
-#if BX_CPU_LEVEL < 2
- /* ??? XT: */
- bx_kbd_port61h_write(value);
-#endif
- break;
-
- default:
- BX_PANIC(("pit: unsupported io write to port %04x = %02x",
- (unsigned) address, (unsigned) value));
- }
-}
-
-
-
-
- void
-bx_pit_c::write_count_reg( Bit8u value, unsigned timerid )
-{
- bx_bool xfer_complete;
-
- switch ( BX_PIT_THIS s.timer[timerid].latch_mode ) {
- case BX_PIT_LATCH_MODE_16BIT: /* write1=LSB, write2=MSB */
- if (BX_PIT_THIS s.timer[timerid].input_latch_toggle==0) {
- BX_PIT_THIS s.timer[timerid].input_latch_value = value;
- BX_PIT_THIS s.timer[timerid].input_latch_toggle = 1;
- xfer_complete = 0;
- if (bx_dbg.pit)
- BX_INFO(("pit: BX_PIT_THIS s.timer[timerid] write L = %02x", (unsigned) value));
- }
- else {
- BX_PIT_THIS s.timer[timerid].input_latch_value |= (value << 8);
- BX_PIT_THIS s.timer[timerid].input_latch_toggle = 0;
- xfer_complete = 1;
- if (bx_dbg.pit)
- BX_INFO(("pit: BX_PIT_THIS s.timer[timerid] write H = %02x", (unsigned) value));
- }
- break;
-
- case BX_PIT_LATCH_MODE_MSB: /* write1=MSB, LSB=0 */
- BX_PIT_THIS s.timer[timerid].input_latch_value = (value << 8);
- xfer_complete = 1;
- if (bx_dbg.pit)
- BX_INFO(("pit: BX_PIT_THIS s.timer[timerid] write H = %02x", (unsigned) value));
- break;
-
- case BX_PIT_LATCH_MODE_LSB: /* write1=LSB, MSB=0 */
- BX_PIT_THIS s.timer[timerid].input_latch_value = value;
- xfer_complete = 1;
- if (bx_dbg.pit)
- BX_INFO(("pit: BX_PIT_THIS s.timer[timerid] write L = %02x", (unsigned) value));
- break;
-
- default:
- BX_PANIC(("write_count_reg: latch_mode unknown"));
- xfer_complete = 0;
- }
-
- if (xfer_complete) {
- BX_PIT_THIS s.timer[timerid].counter_max = BX_PIT_THIS s.timer[timerid].input_latch_value;
-
- // reprogramming counter clears latch
- BX_PIT_THIS s.timer[timerid].output_latch_full = 0;
-
- // counter bounds
- // mode minimum maximum
- // 0 1 0
- // 1 1 0
- // 2 2 0
- // 3 2 0
- // 4 1 0
- // 5 1 0
- switch (BX_PIT_THIS s.timer[timerid].mode) {
- case 0:
- BX_PIT_THIS s.timer[timerid].counter = BX_PIT_THIS s.timer[timerid].counter_max;
- BX_PIT_THIS s.timer[timerid].active = 1;
- if (BX_PIT_THIS s.timer[timerid].GATE) {
- BX_PIT_THIS s.timer[timerid].OUT = 0; // OUT pin starts low
- start( timerid );
- }
- break;
- case 1:
- BX_PANIC(("pit:write_count_reg(%u): mode1 unsupported",
- timerid));
- break;
- case 2:
- if ( BX_PIT_THIS s.timer[timerid].counter_max == 1 )
- BX_PANIC(("pit:write_count_reg(%u): mode %u counter_max=1",
- timerid, (unsigned) BX_PIT_THIS s.timer[timerid].mode));
- if ( BX_PIT_THIS s.timer[timerid].GATE && !BX_PIT_THIS s.timer[timerid].active ) {
- // software triggered
- BX_PIT_THIS s.timer[timerid].counter = BX_PIT_THIS s.timer[timerid].counter_max;
- BX_PIT_THIS s.timer[timerid].active = 1;
- BX_PIT_THIS s.timer[timerid].OUT = 1; // initially set high
- start( timerid );
- }
- break;
- case 3:
- if ( BX_PIT_THIS s.timer[timerid].counter_max == 1 )
- BX_PANIC(("pit:write_count_reg(%u): mode %u counter_max=1",
- timerid, (unsigned) BX_PIT_THIS s.timer[timerid].mode));
- BX_PIT_THIS s.timer[timerid].counter_max = BX_PIT_THIS s.timer[timerid].counter_max & 0xfffe;
- if ( BX_PIT_THIS s.timer[timerid].GATE && !BX_PIT_THIS s.timer[timerid].active ) {
- // software triggered
- BX_PIT_THIS s.timer[timerid].counter = BX_PIT_THIS s.timer[timerid].counter_max;
- BX_PIT_THIS s.timer[timerid].active = 1;
- BX_PIT_THIS s.timer[timerid].OUT = 1; // initially set high
- start( timerid );
- }
- break;
- case 4:
- BX_PANIC(("pit:write_count_reg(%u): mode4 unsupported",
- timerid));
- break;
- case 5:
- BX_PANIC(("pit:write_count_reg(%u): mode5 unsupported",
- timerid));
- break;
- }
- }
-}
-
-
- Bit8u
-bx_pit_c::read_counter( unsigned timerid )
-{
- Bit16u counter_value;
- Bit8u retval;
-
- if (BX_PIT_THIS s.timer[timerid].output_latch_full) { /* latched read */
- counter_value = BX_PIT_THIS s.timer[timerid].output_latch_value;
- }
- else { /* direct unlatched read */
- counter_value = BX_PIT_THIS s.timer[timerid].counter;
-BX_INFO(("CV=%04x", (unsigned) BX_PIT_THIS s.timer[timerid].counter));
- }
-
- switch (BX_PIT_THIS s.timer[timerid].latch_mode) {
- case BX_PIT_LATCH_MODE_LSB:
- retval = (Bit8u ) counter_value;
- BX_PIT_THIS s.timer[timerid].output_latch_full = 0;
- break;
- case BX_PIT_LATCH_MODE_MSB:
- retval = (Bit8u ) ( counter_value >> 8 );
- BX_PIT_THIS s.timer[timerid].output_latch_full = 0;
- break;
- case BX_PIT_LATCH_MODE_16BIT:
- if (BX_PIT_THIS s.timer[timerid].output_latch_toggle==0) { /* LSB 1st */
- retval = (Bit8u ) counter_value;
- }
- else { /* MSB 2nd */
- retval = (Bit8u ) ( counter_value >> 8 );
- }
- BX_PIT_THIS s.timer[timerid].output_latch_toggle = !BX_PIT_THIS s.timer[timerid].output_latch_toggle;
- if (BX_PIT_THIS s.timer[timerid].output_latch_toggle == 0)
- BX_PIT_THIS s.timer[timerid].output_latch_full = 0;
- break;
- default:
- BX_PANIC(("pit: io read from port 40h: unknown latch mode"));
- retval = 0; /* keep compiler happy */
- }
- return( retval );
-}
-
-
- void
-bx_pit_c::latch( unsigned timerid )
-{
- /* subsequent counter latch commands are ignored until value read out */
- if (BX_PIT_THIS s.timer[timerid].output_latch_full) {
- BX_INFO(("pit: pit(%u) latch: output latch full, ignoring",
- timerid));
- return;
- }
-
- BX_PIT_THIS s.timer[timerid].output_latch_value = BX_PIT_THIS s.timer[timerid].counter;
-
- if (bx_dbg.pit)
- BX_INFO(("pit: latch_value = %u", (unsigned) BX_PIT_THIS s.timer[timerid].output_latch_value));
- BX_PIT_THIS s.timer[timerid].output_latch_toggle = 0;
- BX_PIT_THIS s.timer[timerid].output_latch_full = 1;
-}
-
- void
-bx_pit_c::set_GATE(unsigned pit_id, unsigned value)
-{
- // GATE's for Timer 0 & Timer 1 are tied high.
- if (pit_id != 2)
- BX_PANIC(("pit:set_GATE: pit_id != 2"));
-
- value = (value > 0);
-
- /* if no transition of GATE input line, then nothing to do */
- if (value == BX_PIT_THIS s.timer[2].GATE)
- return;
-
- if (value) { /* PIT2: GATE transition from 0 to 1 */
- BX_PIT_THIS s.timer[2].GATE = 1;
- switch ( BX_PIT_THIS s.timer[2].mode ) {
- case 0:
- BX_PIT_THIS s.timer[2].counter = BX_PIT_THIS s.timer[2].counter_max;
- if (BX_PIT_THIS s.timer[2].active) {
- BX_PIT_THIS s.timer[2].OUT = 0;
- }
- start( 2 );
- break;
- case 2:
- // begin counting, reload counter
- BX_PIT_THIS s.timer[2].active = 1;
- BX_PIT_THIS s.timer[2].OUT = 1;
- BX_PIT_THIS s.timer[2].counter = BX_PIT_THIS s.timer[2].counter_max;
- start( 2 );
- break;
- case 3:
- // begin counting, reload counter
- BX_PIT_THIS s.timer[2].active = 1;
- BX_PIT_THIS s.timer[2].OUT = 1;
- BX_PIT_THIS s.timer[2].counter = BX_PIT_THIS s.timer[2].counter_max;
- start( 2 );
- break;
- case 1:
- case 4:
- case 5:
- default:
- BX_PANIC(("bx_pit_c::set_GATE: unhandled timer2 mode %u",
- (unsigned) BX_PIT_THIS s.timer[2].mode));
- }
- }
- else { // PIT2: GATE transition from 1 to 0, deactivate
- BX_PIT_THIS s.timer[2].GATE = 0;
- switch ( BX_PIT_THIS s.timer[2].mode ) {
- case 0:
- break;
- case 2:
- // 1) stops count, 2) OUT goes immediately high
- BX_PIT_THIS s.timer[2].active = 0;
- BX_PIT_THIS s.timer[2].OUT = 1;
- break;
- case 3:
- // 1) stops count, 2) OUT goes immediately high
- BX_PIT_THIS s.timer[2].active = 0;
- BX_PIT_THIS s.timer[2].OUT = 1;
- break;
- case 1:
- case 4:
- case 5:
- default:
- BX_PANIC(("bx_pit_c::set_GATE: unhandled timer2 mode %u",
- (unsigned) BX_PIT_THIS s.timer[2].mode));
- }
- }
-}
-
-
- void
-bx_pit_c::start(unsigned timerid)
-{
- unsigned long period_hz;
-
- if (BX_PIT_THIS s.timer[timerid].counter_max == 0x0000) {
- period_hz = 1193182 / 65536;
- }
- else {
- period_hz = 1193182 / BX_PIT_THIS s.timer[timerid].counter_max;
- }
- BX_INFO(("timer%u period set to %lu hz", timerid, period_hz));
-
-
- switch (BX_PIT_THIS s.timer[timerid].mode) {
- case 0: /* single timeout */
- break;
- case 1: /* retriggerable one-shot */
- BX_PANIC(("start: mode %u unhandled",
- (unsigned) BX_PIT_THIS s.timer[timerid].mode));
- break;
- case 2: /* rate generator */
- break;
- case 3: /* square wave mode */
- break;
- case 4: /* software triggered strobe */
- BX_PANIC(("start: mode %u unhandled",
- (unsigned) BX_PIT_THIS s.timer[timerid].mode));
- break;
- case 5: /* hardware retriggerable strobe */
- BX_PANIC(("start: mode %u unhandled",
- (unsigned) BX_PIT_THIS s.timer[timerid].mode));
- break;
- default:
- BX_PANIC(("start: timer%u has bad mode",
- (unsigned) BX_PIT_THIS s.timer[timerid].mode));
- }
-}
-
-
-
-
- int
-bx_pit_c::SaveState( class state_file *fd )
-{
- fd->write_check ("8254 start");
- fd->write (&BX_PIT_THIS s, sizeof (BX_PIT_THIS s));
- fd->write_check ("8254 end");
- return(0);
-}
-
-
- int
-bx_pit_c::LoadState( class state_file *fd )
-{
- fd->read_check ("8254 start");
- fd->read (&BX_PIT_THIS s, sizeof (BX_PIT_THIS s));
- fd->read_check ("8254 end");
- return(0);
-}
-
-
-#if 0
- void
-bx_kbd_port61h_write(Bit8u value)
-{
-// PcError("KBD_PORT61H_WRITE(): not implemented yet");
- UNUSED( value );
-}
-#endif
-
-
- bx_bool
-bx_pit_c::periodic( Bit32u usec_delta )
-{
- bx_bool prev_timer0_out;
-
- prev_timer0_out = BX_PIT_THIS s.timer[0].OUT;
-
- for (unsigned i = 0; i < 3; i++) {
- // is timer enabled and active?
- if ( BX_PIT_THIS s.timer[i].GATE && BX_PIT_THIS s.timer[i].active ) {
- switch ( BX_PIT_THIS s.timer[i].mode ) {
- case 0: // Mode 0: Single Timeout
- // wraps after count expires
- if ( BX_PIT_THIS s.timer[i].counter == 0 ) {
- // counter previously expired, wrap counter
- BX_PIT_THIS s.timer[i].counter = 0xffff;
- }
- else if ( usec_delta >= BX_PIT_THIS s.timer[i].counter ) {
- // counter expired
- BX_PIT_THIS s.timer[i].counter = 0;
- BX_PIT_THIS s.timer[i].OUT = 1;
- }
- else {
- // decrement counter by elapsed useconds
- BX_PIT_THIS s.timer[i].counter -= (Bit16u ) usec_delta;
- }
- break;
-
- case 1: // Mode 1: Retriggerable One-Shot
- // wraps after count expires
- BX_PANIC(("bx_pit_c::periodic: bad mode: timer[%u], mode %u",
- i, (unsigned) BX_PIT_THIS s.timer[i].mode));
- break;
-
- case 2: // Mode 2: Rate Generator
- // reloads after count expires
- // OUT is low when counter=1, high otherwise
- // min count=2, max count=0
- if ( BX_PIT_THIS s.timer[i].counter == 0 ) {
- // max counter val, just wrap
- BX_PIT_THIS s.timer[i].counter = 0xffff;
- BX_PIT_THIS s.timer[i].OUT = 1;
- }
- else if ( BX_PIT_THIS s.timer[i].counter == 1 ) {
- // counter previously expired, reload
- BX_PIT_THIS s.timer[i].counter = BX_PIT_THIS s.timer[i].counter_max;
- BX_PIT_THIS s.timer[i].OUT = 1;
- }
- else if ( (BX_PIT_THIS s.timer[i].counter == 2) ||
- (usec_delta >= (Bit32u(BX_PIT_THIS s.timer[i].counter) - 1)) ) {
- // in either case, counter will reach 1
- BX_PIT_THIS s.timer[i].counter = 1;
- BX_PIT_THIS s.timer[i].OUT = 0;
- }
- else {
- // decrement counter by elapsed useconds
- BX_PIT_THIS s.timer[i].counter -= (Bit16u ) usec_delta;
- }
- break;
-
- case 3: // Mode 3: Square Wave Mode
- // reloads after count expires
- // min count=2, max count=0
- if ( BX_PIT_THIS s.timer[i].counter == 0 ) {
- // max count, dec by 2
- BX_PIT_THIS s.timer[i].counter = 0xfffe;
- }
- else if ( (BX_PIT_THIS s.timer[i].counter <= 2) ||
- ( (usec_delta*2) >= BX_PIT_THIS s.timer[i].counter ) ) {
- // counter expired, reload
- BX_PIT_THIS s.timer[i].counter = BX_PIT_THIS s.timer[i].counter_max;
- BX_PIT_THIS s.timer[i].OUT = !BX_PIT_THIS s.timer[i].OUT;
- //BX_INFO(("CV: reload t%u to %04x", (unsigned) i, (unsigned)
- // BX_PIT_THIS s.timer[i].counter));
- }
- else {
- // decrement counter by elapsed useconds
- BX_PIT_THIS s.timer[i].counter -= (Bit16u ) ( 2*usec_delta );
- //BX_INFO(("CV: dec count to %04x",
- // (unsigned) BX_PIT_THIS s.timer[i].counter));
- }
- break;
-
- case 4: // Mode 4: Software Triggered Strobe
- // wraps after count expires
- BX_PANIC(("bx_pit_c::periodic: bad mode: timer[%u], mode %u",
- i, (unsigned) BX_PIT_THIS s.timer[i].mode));
- break;
-
- case 5: // Mode 5: Hardware Retriggerable Strobe
- // wraps after count expires
- BX_PANIC(("bx_pit_c::periodic: bad mode: timer[%u], mode %u",
- i, (unsigned) BX_PIT_THIS s.timer[i].mode));
- break;
- default:
- BX_PANIC(("bx_pit_c::periodic: bad mode: timer[%u], mode %u",
- i, (unsigned) BX_PIT_THIS s.timer[i].mode));
- break;
- } // switch ( BX_PIT_THIS s.tim...
- } // if ( BX_PIT_THIS s.timer[i]...
- } // for (unsigned i...
-
- // see if there's a rising edge on timer0's output to trigger an IRQ0.
- if ( (prev_timer0_out==0) && (BX_PIT_THIS s.timer[0].OUT==1) )
- return(1); // request IRQ 0
- else
- return(0);
-}
-
-#endif // #if (BX_USE_NEW_PIT==0)
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: pit.h,v 1.10 2002/10/25 11:44:40 bdenney Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2001 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-#ifndef _BX_PIT_H
-#define _BX_PIT_H
-
-#include "config.h"
-
-#if (BX_USE_NEW_PIT==0)
-
-#if BX_USE_PIT_SMF
-# define BX_PIT_SMF static
-# define BX_PIT_THIS bx_pit.
-#else
-# define BX_PIT_SMF
-# define BX_PIT_THIS this->
-#endif
-
-#ifdef OUT
-# undef OUT
-#endif
-
-
-typedef struct {
- Bit8u mode;
- Bit8u latch_mode;
- Bit16u input_latch_value;
- bx_bool input_latch_toggle;
- Bit16u output_latch_value;
- bx_bool output_latch_toggle;
- bx_bool output_latch_full;
- Bit16u counter_max;
- Bit16u counter;
- bx_bool bcd_mode;
- bx_bool active;
- bx_bool GATE; // GATE input pin
- bx_bool OUT; // OUT output pin
- } bx_pit_t;
-
-
-
-
-class bx_pit_c : public logfunctions {
-public:
- bx_pit_c( void );
- ~bx_pit_c( void );
- BX_PIT_SMF int init(void);
- BX_PIT_SMF void reset( unsigned type);
- BX_PIT_SMF bx_bool periodic( Bit32u usec_delta );
-
- BX_PIT_SMF int SaveState( class state_file *fd );
- BX_PIT_SMF int LoadState( class state_file *fd );
-
-private:
-
- static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len);
- static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len);
-#if !BX_USE_PIT_SMF
- Bit32u read( Bit32u addr, unsigned int len );
- void write( Bit32u addr, Bit32u Value, unsigned int len );
-#endif
-
- struct s_type {
- bx_pit_t timer[3];
- Bit8u speaker_data_on;
- bx_bool refresh_clock_div2;
- int timer_handle[3];
- } s;
-
- BX_PIT_SMF void write_count_reg( Bit8u value, unsigned timerid );
- BX_PIT_SMF Bit8u read_counter( unsigned timerid );
- BX_PIT_SMF void latch( unsigned timerid );
- BX_PIT_SMF void set_GATE(unsigned pit_id, unsigned value);
- BX_PIT_SMF void start(unsigned timerid);
- };
-
-extern bx_pit_c bx_pit;
-
-#endif // #if (BX_USE_NEW_PIT==0)
-#endif // #ifndef _BX_PIT_H
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: pit82c54.cc,v 1.23 2003/06/29 17:24:52 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-/*
- * Emulator of an Intel 8254/82C54 Programmable Interval Timer.
- * Greg Alexander <yakovlev@usa.com>
- *
- *
- * Things I am unclear on (greg):
- * 1.)What happens if both the status and count registers are latched,
- * but the first of the two count registers has already been read?
- * I.E.:
- * latch count 0 (16-bit)
- * Read count 0 (read LSByte)
- * READ_BACK status of count 0
- * Read count 0 - do you get MSByte or status?
- * This will be flagged as an error.
- * 2.)What happens when we latch the output in the middle of a 2-part
- * unlatched read?
- * 3.)I assumed that programming a counter removes a latched status.
- * 4.)I implemented the 8254 description of mode 0, not the 82C54 one.
- * 5.)clock() calls represent a rising clock edge followed by a falling
- * clock edge.
- * 6.)What happens when we trigger mode 1 in the middle of a 2-part
- * write?
- */
-
-#include "bochs.h"
-#include "pit82c54.h"
-#define LOG_THIS this->
-
-
-void pit_82C54::print_counter(counter_type & thisctr) {
-#if 1
- BX_INFO(("Printing Counter"));
- BX_INFO(("count: %d",thisctr.count));
- BX_INFO(("count_binary: %x",thisctr.count_binary));
- BX_INFO(("counter gate: %x",thisctr.GATE));
- BX_INFO(("counter OUT: %x",thisctr.OUTpin));
- BX_INFO(("next_change_time: %d",thisctr.next_change_time));
- BX_INFO(("End Counter Printout"));
-#endif
-}
-
-void pit_82C54::print_cnum(Bit8u cnum) {
- if(cnum>MAX_COUNTER) {
- BX_ERROR(("Bad counter index to print_cnum"));
- } else {
- print_counter(counter[cnum]);
- }
-}
-
- void pit_82C54::latch_counter(counter_type & thisctr) {
- if(thisctr.count_LSB_latched || thisctr.count_MSB_latched) {
- //Do nothing because previous latch has not been read.;
- } else {
- switch(thisctr.read_state) {
- case MSByte:
- thisctr.outlatch=thisctr.count & 0xFFFF;
- thisctr.count_MSB_latched=1;
- break;
- case LSByte:
- thisctr.outlatch=thisctr.count & 0xFFFF;
- thisctr.count_LSB_latched=1;
- break;
- case LSByte_multiple:
- thisctr.outlatch=thisctr.count & 0xFFFF;
- thisctr.count_LSB_latched=1;
- thisctr.count_MSB_latched=1;
- break;
- case MSByte_multiple:
- if(!(seen_problems & UNL_2P_READ)) {
-// seen_problems|=UNL_2P_READ;
- BX_ERROR(("Unknown behavior when latching during 2-part read."));
- BX_ERROR((" This message will not be repeated."));
- }
- //I guess latching and resetting to LSB first makes sense;
- BX_DEBUG(("Setting read_state to LSB_mult"));
- thisctr.read_state=LSByte_multiple;
- thisctr.outlatch=thisctr.count & 0xFFFF;
- thisctr.count_LSB_latched=1;
- thisctr.count_MSB_latched=1;
- break;
- default:
- BX_ERROR(("Unknown read mode found during latch command."));
- break;
- }
- }
- }
-
- void pit_82C54::set_OUT (counter_type & thisctr, bool data) {
- //This will probably have a callback, so I put it here.
- thisctr.OUTpin=data;
- }
-
- void BX_CPP_AttrRegparmN(2)
-pit_82C54::set_count (counter_type & thisctr, Bit32u data) {
- thisctr.count=data & 0xFFFF;
- set_binary_to_count(thisctr);
- }
-
- void BX_CPP_AttrRegparmN(1)
-pit_82C54::set_count_to_binary(counter_type & thisctr) {
- if(thisctr.bcd_mode) {
- thisctr.count=
- (((thisctr.count_binary/1)%10)<<0) |
- (((thisctr.count_binary/10)%10)<<4) |
- (((thisctr.count_binary/100)%10)<<8) |
- (((thisctr.count_binary/1000)%10)<<12)
- ;
- } else {
- thisctr.count=thisctr.count_binary;
- }
- }
-
- void BX_CPP_AttrRegparmN(1)
-pit_82C54::set_binary_to_count(counter_type & thisctr) {
- if(thisctr.bcd_mode) {
- thisctr.count_binary=
- (1*((thisctr.count>>0)&0xF)) +
- (10*((thisctr.count>>4)&0xF)) +
- (100*((thisctr.count>>8)&0xF)) +
- (1000*((thisctr.count>>12)&0xF))
- ;
- } else {
- thisctr.count_binary=thisctr.count;
- }
- }
-
- void BX_CPP_AttrRegparmN(1)
-pit_82C54::decrement (counter_type & thisctr) {
- if(!thisctr.count) {
- if(thisctr.bcd_mode) {
- thisctr.count=0x9999;
- thisctr.count_binary=9999;
- } else {
- thisctr.count=0xFFFF;
- thisctr.count_binary=0xFFFF;
- }
- } else {
- thisctr.count_binary--;
- set_count_to_binary(thisctr);
- }
- }
-
- void pit_82C54::init (void) {
- Bit8u i;
-
- put("PIT81");
- settype(PIT81LOG);
-
- for(i=0;i<3;i++) {
- BX_DEBUG(("Setting read_state to LSB"));
- counter[i].read_state=LSByte;
- counter[i].write_state=LSByte;
- counter[i].GATE=1;
- counter[i].OUTpin=1;
- counter[i].triggerGATE=0;
- counter[i].mode=4;
- counter[i].first_pass=0;
- counter[i].bcd_mode=0;
- counter[i].count=0;
- counter[i].count_binary=0;
- counter[i].state_bit_1=0;
- counter[i].state_bit_2=0;
- counter[i].null_count=0;
- counter[i].rw_mode=1;
- counter[i].count_written=1;
- counter[i].count_LSB_latched=0;
- counter[i].count_MSB_latched=0;
- counter[i].status_latched=0;
- counter[i].next_change_time=0;
- }
- seen_problems=0;
- }
-
- pit_82C54::pit_82C54 (void) {
- init();
- }
-
- void pit_82C54::reset (unsigned type) {
- }
-
-void BX_CPP_AttrRegparmN(2)
-pit_82C54::decrement_multiple(counter_type & thisctr, Bit32u cycles) {
- while(cycles>0) {
- if(cycles<=thisctr.count_binary) {
- thisctr.count_binary-=cycles;
- cycles-=cycles;
- set_count_to_binary(thisctr);
- } else {
- cycles-=(thisctr.count_binary+1);
- thisctr.count_binary-=thisctr.count_binary;
- set_count_to_binary(thisctr);
- decrement(thisctr);
- }
- }
-}
-
-void pit_82C54::clock_multiple(Bit8u cnum, Bit32u cycles) {
- if(cnum>MAX_COUNTER) {
- BX_ERROR(("Counter number too high in clock"));
- } else {
- counter_type & thisctr = counter[cnum];
- while(cycles>0) {
- if(thisctr.next_change_time==0) {
- if(thisctr.count_written) {
- switch(thisctr.mode) {
- case 0:
- if(thisctr.GATE && (thisctr.write_state!=MSByte_multiple)) {
- decrement_multiple(thisctr, cycles);
- }
- break;
- case 1:
- decrement_multiple(thisctr, cycles);
- break;
- case 2:
- if( (!thisctr.first_pass) && thisctr.GATE ) {
- decrement_multiple(thisctr, cycles);
- }
- break;
- case 3:
- if( (!thisctr.first_pass) && thisctr.GATE ) {
- decrement_multiple(thisctr, 2*cycles);
- }
- break;
- case 4:
- if(thisctr.GATE) {
- decrement_multiple(thisctr, cycles);
- }
- break;
- case 5:
- decrement_multiple(thisctr, cycles);
- break;
- default:
- break;
- }
- }
- cycles-=cycles;
- } else {
- switch(thisctr.mode) {
- case 0:
- case 1:
- case 2:
- case 4:
- case 5:
- if( thisctr.next_change_time > cycles ) {
- decrement_multiple(thisctr,cycles);
- thisctr.next_change_time-=cycles;
- cycles-=cycles;
- } else {
- decrement_multiple(thisctr,(thisctr.next_change_time-1));
- cycles-=thisctr.next_change_time;
- clock(cnum);
- }
- break;
- case 3:
- if( thisctr.next_change_time > cycles ) {
- decrement_multiple(thisctr,cycles*2);
- thisctr.next_change_time-=cycles;
- cycles-=cycles;
- } else {
- decrement_multiple(thisctr,(thisctr.next_change_time-1)*2);
- cycles-=thisctr.next_change_time;
- clock(cnum);
- }
- break;
- default:
- cycles-=cycles;
- break;
- }
- }
- }
-#if 0
- print_counter(thisctr);
-#endif
- }
-}
-
- void BX_CPP_AttrRegparmN(1)
-pit_82C54::clock(Bit8u cnum) {
- if(cnum>MAX_COUNTER) {
- BX_ERROR(("Counter number too high in clock"));
- } else {
- counter_type & thisctr = counter[cnum];
- switch(thisctr.mode) {
- case 0:
- if(thisctr.count_written) {
- if(thisctr.null_count) {
- set_count(thisctr, thisctr.inlatch);
- if(thisctr.GATE) {
- if(thisctr.count_binary==0) {
- thisctr.next_change_time=1;
- } else {
- thisctr.next_change_time=thisctr.count_binary & 0xFFFF;
- }
- } else {
- thisctr.next_change_time=0;
- }
- thisctr.null_count=0;
- } else {
- if(thisctr.GATE && (thisctr.write_state!=MSByte_multiple)) {
- decrement(thisctr);
- if(!thisctr.OUTpin) {
- thisctr.next_change_time=thisctr.count_binary & 0xFFFF;
- if(!thisctr.count) {
- set_OUT(thisctr,1);
- }
- } else {
- thisctr.next_change_time=0;
- }
- } else {
- thisctr.next_change_time=0; //if the clock isn't moving.
- }
- }
- } else {
- thisctr.next_change_time=0; //default to 0.
- }
- thisctr.triggerGATE=0;
- break;
- case 1:
- if(thisctr.count_written) {
- if(thisctr.triggerGATE) {
- set_count(thisctr, thisctr.inlatch);
- if(thisctr.count_binary==0) {
- thisctr.next_change_time=1;
- } else {
- thisctr.next_change_time=thisctr.count_binary & 0xFFFF;
- }
- thisctr.null_count=0;
- set_OUT(thisctr,0);
- if(thisctr.write_state==MSByte_multiple) {
- BX_ERROR(("Undefined behavior when loading a half loaded count."));
- }
- } else {
- decrement(thisctr);
- if(!thisctr.OUTpin) {
- if(thisctr.count_binary==0) {
- thisctr.next_change_time=1;
- } else {
- thisctr.next_change_time=thisctr.count_binary & 0xFFFF;
- }
- if(thisctr.count==0) {
- set_OUT(thisctr,1);
- }
- } else {
- thisctr.next_change_time=0;
- }
- }
- } else {
- thisctr.next_change_time=0; //default to 0.
- }
- thisctr.triggerGATE=0;
- break;
- case 2:
- if(thisctr.count_written) {
- if(thisctr.triggerGATE || thisctr.first_pass) {
- set_count(thisctr, thisctr.inlatch);
- thisctr.next_change_time=(thisctr.count_binary-1) & 0xFFFF;
- thisctr.null_count=0;
- if(thisctr.inlatch==1) {
- BX_ERROR(("ERROR: count of 1 is invalid in pit mode 2."));
- }
- if(!thisctr.OUTpin) {
- set_OUT(thisctr,1);
- }
- if(thisctr.write_state==MSByte_multiple) {
- BX_ERROR(("Undefined behavior when loading a half loaded count."));
- }
- thisctr.first_pass=0;
- } else {
- if(thisctr.GATE) {
- decrement(thisctr);
- thisctr.next_change_time=(thisctr.count_binary-1) & 0xFFFF;
- if(thisctr.count==1) {
- thisctr.next_change_time=1;
- set_OUT(thisctr,0);
- thisctr.first_pass=1;
- }
- } else {
- thisctr.next_change_time=0;
- }
- }
- } else {
- thisctr.next_change_time=0;
- }
- thisctr.triggerGATE=0;
- break;
- case 3:
- if(thisctr.count_written) {
- if( (thisctr.triggerGATE || thisctr.first_pass
- || thisctr.state_bit_2) && thisctr.GATE ) {
- set_count(thisctr, thisctr.inlatch & 0xFFFE);
- thisctr.state_bit_1=thisctr.inlatch & 0x1;
- if( (!thisctr.OUTpin) || (!(thisctr.state_bit_1))) {
- if(((thisctr.count_binary/2)-1)==0) {
- thisctr.next_change_time=1;
- } else {
- thisctr.next_change_time=((thisctr.count_binary/2)-1) & 0xFFFF;
- }
- } else {
- if((thisctr.count_binary/2)==0) {
- thisctr.next_change_time=1;
- } else {
- thisctr.next_change_time=(thisctr.count_binary/2) & 0xFFFF;
- }
- }
- thisctr.null_count=0;
- if(thisctr.inlatch==1) {
- BX_ERROR(("Count of 1 is invalid in pit mode 3."));
- }
- if(!thisctr.OUTpin) {
- set_OUT(thisctr,1);
- } else if(thisctr.OUTpin && !thisctr.first_pass) {
- set_OUT(thisctr,0);
- }
- if(thisctr.write_state==MSByte_multiple) {
- BX_ERROR(("Undefined behavior when loading a half loaded count."));
- }
- thisctr.state_bit_2=0;
- thisctr.first_pass=0;
- } else {
- if(thisctr.GATE) {
- decrement(thisctr);
- decrement(thisctr);
- if( (!thisctr.OUTpin) || (!(thisctr.state_bit_1))) {
- thisctr.next_change_time=((thisctr.count_binary/2)-1) & 0xFFFF;
- } else {
- thisctr.next_change_time=(thisctr.count_binary/2) & 0xFFFF;
- }
- if(thisctr.count==0) {
- thisctr.state_bit_2=1;
- thisctr.next_change_time=1;
- }
- if( (thisctr.count==2) &&
- ( (!thisctr.OUTpin) || (!(thisctr.state_bit_1)))
- ) {
- thisctr.state_bit_2=1;
- thisctr.next_change_time=1;
- }
- } else {
- thisctr.next_change_time=0;
- }
- }
- } else {
- thisctr.next_change_time=0;
- }
- thisctr.triggerGATE=0;
- break;
- case 4:
- if(thisctr.count_written) {
- if(!thisctr.OUTpin) {
- set_OUT(thisctr,1);
- }
- if(thisctr.null_count) {
- set_count(thisctr, thisctr.inlatch);
- if(thisctr.GATE) {
- if(thisctr.count_binary==0) {
- thisctr.next_change_time=1;
- } else {
- thisctr.next_change_time=thisctr.count_binary & 0xFFFF;
- }
- } else {
- thisctr.next_change_time=0;
- }
- thisctr.null_count=0;
- if(thisctr.write_state==MSByte_multiple) {
- BX_ERROR(("Undefined behavior when loading a half loaded count."));
- }
- thisctr.first_pass=1;
- } else {
- if(thisctr.GATE) {
- decrement(thisctr);
- if(thisctr.first_pass) {
- thisctr.next_change_time=thisctr.count_binary & 0xFFFF;
- if(!thisctr.count) {
- set_OUT(thisctr,0);
- thisctr.next_change_time=1;
- thisctr.first_pass=0;
- }
- } else {
- thisctr.next_change_time=0;
- }
- } else {
- thisctr.next_change_time=0;
- }
- }
- } else {
- thisctr.next_change_time=0;
- }
- thisctr.triggerGATE=0;
- break;
- case 5:
- if(thisctr.count_written) {
- if(!thisctr.OUTpin) {
- set_OUT(thisctr,1);
- }
- if(thisctr.triggerGATE) {
- set_count(thisctr, thisctr.inlatch);
- if(thisctr.count_binary==0) {
- thisctr.next_change_time=1;
- } else {
- thisctr.next_change_time=thisctr.count_binary & 0xFFFF;
- }
- thisctr.null_count=0;
- if(thisctr.write_state==MSByte_multiple) {
- BX_ERROR(("Undefined behavior when loading a half loaded count."));
- }
- thisctr.first_pass=1;
- } else {
- decrement(thisctr);
- if(thisctr.first_pass) {
- thisctr.next_change_time=thisctr.count_binary & 0xFFFF;
- if(!thisctr.count) {
- set_OUT(thisctr,0);
- thisctr.next_change_time=1;
- thisctr.first_pass=0;
- }
- } else {
- thisctr.next_change_time=0;
- }
- }
- } else {
- thisctr.next_change_time=0;
- }
- thisctr.triggerGATE=0;
- break;
- default:
- BX_ERROR(("Mode not implemented."));
- thisctr.next_change_time=0;
- thisctr.triggerGATE=0;
- break;
- }
- }
- }
-
- void pit_82C54::clock_all(Bit32u cycles) {
- BX_DEBUG(("clock_all: cycles=%d",cycles));
- clock_multiple(0,cycles);
- clock_multiple(1,cycles);
- clock_multiple(2,cycles);
- }
-
- Bit8u pit_82C54::read(Bit8u address) {
- if(address>MAX_ADDRESS) {
- BX_ERROR(("Counter address incorrect in data read."));
- } else if(address==CONTROL_ADDRESS) {
- BX_DEBUG(("PIT Read: Control Word Register."));
- //Read from control word register;
- /* This might be okay. If so, 0 seems the most logical
- * return value from looking at the docs.
- */
- BX_ERROR(("Read from control word register not defined."));
- return 0;
- } else {
- //Read from a counter;
- BX_DEBUG(("PIT Read: Counter %d.",address));
- counter_type & thisctr=counter[address];
- if(thisctr.status_latched) {
- //Latched Status Read;
- if(thisctr.count_MSB_latched &&
- (thisctr.read_state==MSByte_multiple) ) {
- BX_ERROR(("Undefined output when status latched and count half read."));
- } else {
- thisctr.status_latched=0;
- return thisctr.status_latch;
- }
- } else {
- //Latched Count Read;
- if(thisctr.count_LSB_latched) {
- //Read Least Significant Byte;
- if(thisctr.read_state==LSByte_multiple) {
- BX_DEBUG(("Setting read_state to MSB_mult"));
- thisctr.read_state=MSByte_multiple;
- }
- thisctr.count_LSB_latched=0;
- return (thisctr.outlatch & 0xFF);
- } else if(thisctr.count_MSB_latched) {
- //Read Most Significant Byte;
- if(thisctr.read_state==MSByte_multiple) {
- BX_DEBUG(("Setting read_state to LSB_mult"));
- thisctr.read_state=LSByte_multiple;
- }
- thisctr.count_MSB_latched=0;
- return ((thisctr.outlatch>>8) & 0xFF);
- } else {
- //Unlatched Count Read;
- if(!(thisctr.read_state & 0x1)) {
- //Read Least Significant Byte;
- if(thisctr.read_state==LSByte_multiple) {
- thisctr.read_state=MSByte_multiple;
- BX_DEBUG(("Setting read_state to MSB_mult"));
- }
- return (thisctr.count & 0xFF);
- } else {
- //Read Most Significant Byte;
- if(thisctr.read_state==MSByte_multiple) {
- BX_DEBUG(("Setting read_state to LSB_mult"));
- thisctr.read_state=LSByte_multiple;
- }
- return ((thisctr.count>>8) & 0xFF);
- }
- }
- }
- }
- //Should only get here on errors;
- return 0;
- }
-
-#ifdef BX_VMX_PIT
-//extra operations when use vmx pit device model
- void pit_82C54::write_initcount_vmx(Bit8u cnum) {
- if(cnum>MAX_COUNTER) {
- BX_ERROR(("Counter number incorrect\n"));
- }
-
- ioreq_t *req = &((vcpu_iodata_t *) shared_page)->vp_ioreq;
- extern bx_pic_c *thePic;
- counter_type & thisctr = counter[cnum];
- if(req->pdata_valid) {
- BX_ERROR(("VMX_PIT:err!pit is port io!\n"));
- }
-
- if (thisctr.mode == 2) {//periodic mode, need HV to help send interrupt
- req->state = STATE_IORESP_HOOK;
-
-// req->u.data = thisctr.inlatch * 1000 / PIT_FREQ;//init count:16 bit
- req->u.data = thisctr.inlatch; //init count:16 bit
- //get the pit irq(0)'s vector from pic DM
- req->u.data |= ((thePic->irq_to_vec(0)) << 16 ); //timer vec:8 bit
- req->u.data |= (cnum << 24); //PIT channel(0~2):2 bit
- req->u.data |= ((thisctr.rw_mode) << 26); //rw mode:2 bit
-
- BX_INFO(("VMX_PIT:whole pit hook packet = 0x%llx \n", (req->u.data ) ));
- BX_INFO(("VMX_PIT:init counter = %d ms\n", (req->u.data & 0xFFFF) ));
- }
-
- }
-#endif
-
- void pit_82C54::write(Bit8u address, Bit8u data) {
- if(address>MAX_ADDRESS) {
- BX_ERROR(("Counter address incorrect in data write."));
- } else if(address==CONTROL_ADDRESS) {
- Bit8u SC, RW, M, BCD;
- controlword=data;
- BX_DEBUG(("Control Word Write."));
- SC = (controlword>>6) & 0x3;
- RW = (controlword>>4) & 0x3;
- M = (controlword>>1) & 0x7;
- BCD = controlword & 0x1;
- if(SC == 3) {
- //READ_BACK command;
- int i;
- BX_DEBUG(("READ_BACK command."));
- for(i=0;i<=MAX_COUNTER;i++) {
- if((M>>i) & 0x1) {
- //If we are using this counter;
- counter_type & thisctr=counter[i];
- if(!((controlword>>5) & 1)) {
- //Latch Count;
- latch_counter(thisctr);
- }
- if(!((controlword>>4) & 1)) {
- //Latch Status;
- if(thisctr.status_latched) {
- //Do nothing because latched status has not been read.;
- } else {
- thisctr.status_latch=
- ((thisctr.OUTpin & 0x1) << 7) |
- ((thisctr.null_count & 0x1) << 6) |
- ((thisctr.rw_mode & 0x3) << 4) |
- ((thisctr.mode & 0x7) << 1) |
- (thisctr.bcd_mode&0x1)
- ;
- thisctr.status_latched=1;
- }
- }
- }
- }
- } else {
- counter_type & thisctr = counter[SC];
- if(!RW) {
- //Counter Latch command;
- BX_DEBUG(("Counter Latch command. SC=%d",SC));
- latch_counter(thisctr);
- } else {
- //Counter Program Command;
- BX_DEBUG(("Counter Program command. SC=%d, RW=%d, M=%d, BCD=%d",SC,RW,M,BCD));
- thisctr.null_count=1;
- thisctr.count_LSB_latched=0;
- thisctr.count_MSB_latched=0;
- thisctr.status_latched=0;
- thisctr.inlatch=0;
- thisctr.count_written=0;
- thisctr.first_pass=1;
- thisctr.rw_mode=RW;
- thisctr.bcd_mode=(BCD > 0);
- thisctr.mode=M;
- switch(RW) {
- case 0x1:
- BX_DEBUG(("Setting read_state to LSB"));
- thisctr.read_state=LSByte;
- thisctr.write_state=LSByte;
- break;
- case 0x2:
- BX_DEBUG(("Setting read_state to MSB"));
- thisctr.read_state=MSByte;
- thisctr.write_state=MSByte;
- break;
- case 0x3:
- BX_DEBUG(("Setting read_state to LSB_mult"));
- thisctr.read_state=LSByte_multiple;
- thisctr.write_state=LSByte_multiple;
- break;
- default:
- BX_ERROR(("RW field invalid in control word write."));
- break;
- }
- //All modes except mode 0 have initial output of 1.;
- if(M) {
- set_OUT(thisctr, 1);
- } else {
- set_OUT(thisctr, 0);
- }
- thisctr.next_change_time=0;
- }
- }
- } else {
- //Write to counter initial value.
- counter_type & thisctr = counter[address];
- BX_DEBUG(("Write Initial Count: counter=%d, count=%d",address,data));
- switch(thisctr.write_state) {
- case LSByte_multiple:
- thisctr.inlatch=(thisctr.inlatch & (0xFF<<8)) | data;
- thisctr.write_state=MSByte_multiple;
- break;
- case LSByte:
- thisctr.inlatch=(thisctr.inlatch & (0xFF<<8)) | data;
- thisctr.null_count=1;
- thisctr.count_written=1;
-#ifdef BX_VMX_PIT
- write_initcount_vmx(address);
-#endif
- break;
- case MSByte_multiple:
- thisctr.write_state=LSByte_multiple;
- case MSByte: //shared between MSB_multiple and MSByte
- thisctr.inlatch=(thisctr.inlatch & 0xFF) | (data<<8);
- thisctr.null_count=1;
- thisctr.count_written=1;
-#ifdef BX_VMX_PIT
- write_initcount_vmx(address);
-#endif
- break;
- default:
- BX_ERROR(("write counter in invalid write state."));
- break;
- }
- switch(thisctr.mode) {
- case 0:
- if(thisctr.write_state==MSByte_multiple) {
- set_OUT(thisctr,0);
- }
- thisctr.next_change_time=1;
- break;
- case 1:
- if(thisctr.triggerGATE) { //for initial writes, if already saw trigger.
- thisctr.next_change_time=1;
- } //Otherwise, no change.
- break;
- case 6:
- case 2:
- thisctr.next_change_time=1; //FIXME: this could be loosened.
- break;
- case 7:
- case 3:
- thisctr.next_change_time=1; //FIXME: this could be loosened.
- break;
- case 4:
- thisctr.next_change_time=1;
- break;
- case 5:
- if(thisctr.triggerGATE) { //for initial writes, if already saw trigger.
- thisctr.next_change_time=1;
- } //Otherwise, no change.
- break;
- }
- }
- }
-
- void pit_82C54::set_GATE(Bit8u cnum, bool data) {
- if(cnum>MAX_COUNTER) {
- BX_ERROR(("Counter number incorrect in 82C54 set_GATE"));
- } else {
- counter_type & thisctr = counter[cnum];
- if(!( (thisctr.GATE&&data) || (!(thisctr.GATE||data)) )) {
- BX_INFO(("Changing GATE %d to: %d",cnum,data));
- thisctr.GATE=data;
- if(thisctr.GATE) {
- thisctr.triggerGATE=1;
- }
- switch(thisctr.mode) {
- case 0:
- if(data && thisctr.count_written) {
- if(thisctr.null_count) {
- thisctr.next_change_time=1;
- } else {
- if( (!thisctr.OUTpin) &&
- (thisctr.write_state!=MSByte_multiple)
- ) {
- if(thisctr.count_binary==0) {
- thisctr.next_change_time=1;
- } else {
- thisctr.next_change_time=thisctr.count_binary & 0xFFFF;
- }
- } else {
- thisctr.next_change_time=0;
- }
- }
- } else {
- if(thisctr.null_count) {
- thisctr.next_change_time=1;
- } else {
- thisctr.next_change_time=0;
- }
- }
- break;
- case 1:
- if(data && thisctr.count_written) { //only triggers cause a change.
- thisctr.next_change_time=1;
- }
- break;
- case 2:
- if(!data) {
- set_OUT(thisctr,1);
- thisctr.next_change_time=0;
- } else {
- if(thisctr.count_written) {
- thisctr.next_change_time=1;
- } else {
- thisctr.next_change_time=0;
- }
- }
- break;
- case 3:
- if(!data) {
- set_OUT(thisctr,1);
- thisctr.first_pass=1;
- thisctr.next_change_time=0;
- } else {
- if(thisctr.count_written) {
- thisctr.next_change_time=1;
- } else {
- thisctr.next_change_time=0;
- }
- }
- break;
- case 4:
- if(!thisctr.OUTpin || thisctr.null_count) {
- thisctr.next_change_time=1;
- } else {
- if(data && thisctr.count_written) {
- if(thisctr.first_pass) {
- if(thisctr.count_binary==0) {
- thisctr.next_change_time=1;
- } else {
- thisctr.next_change_time=thisctr.count_binary & 0xFFFF;
- }
- } else {
- thisctr.next_change_time=0;
- }
- } else {
- thisctr.next_change_time=0;
- }
- }
- break;
- case 5:
- if(data && thisctr.count_written) { //only triggers cause a change.
- thisctr.next_change_time=1;
- }
- break;
- default:
- break;
- }
- }
- }
- }
-
- bool pit_82C54::read_OUT(Bit8u cnum) {
- if(cnum>MAX_COUNTER) {
- BX_ERROR(("Counter number incorrect in 82C54 read_OUT"));
- return 0;
- } else {
- return counter[cnum].OUTpin;
- }
- }
-
- bool pit_82C54::read_GATE(Bit8u cnum) {
- if(cnum>MAX_COUNTER) {
- BX_ERROR(("Counter number incorrect in 82C54 read_GATE"));
- return 0;
- } else {
- return counter[cnum].GATE;
- }
- }
-
-Bit32u pit_82C54::get_clock_event_time(Bit8u cnum) {
- if(cnum>MAX_COUNTER) {
- BX_ERROR(("Counter number incorrect in 82C54 read_GATE"));
- return 0;
- } else {
- return counter[cnum].next_change_time;
- }
-}
-
-Bit32u pit_82C54::get_next_event_time(void) {
- Bit32u out;
- Bit32u time0=get_clock_event_time(0);
- Bit32u time1=get_clock_event_time(1);
- Bit32u time2=get_clock_event_time(2);
-
- out=time0;
- if(time1 && (time1<out))
- out=time1;
- if(time2 && (time2<out))
- out=time2;
- return out;
-}
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: pit82c54.h,v 1.12 2003/03/02 23:59:11 cbothamy Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-/*
- * Emulator of an Intel 8254/82C54 Programmable Interval Timer.
- * Greg Alexander <yakovlev@usa.com>
- *
- * This code is not yet linked into Bochs, but has been included so
- * that you can experiment with it. (bbd)
- */
-
-#ifndef _PIT_82C54_H_
-#define _PIT_82C54_H_ 1
-
-#include "bochs.h"
-
-#ifdef BX_USE_VMX
-#define BX_VMX_PIT 1
-#define PIT_FREQ 1193181
-#endif
-
-
-class pit_82C54 : public logfunctions {
-
-public:
- //Please do not use these. They are public because they have to be
- // to compile on some platforms. They are not to be used by other
- // classes.
-
- enum rw_status {
- LSByte=0,
- MSByte=1,
- LSByte_multiple=2,
- MSByte_multiple=3
- };
-
-private:
-
- enum {
- MAX_COUNTER=2,
- MAX_ADDRESS=3,
- CONTROL_ADDRESS=3,
- MAX_MODE=5
- };
-
- enum real_RW_status {
- LSB_real=1,
- MSB_real=2,
- BOTH_real=3
- };
-
- enum problem_type {
- UNL_2P_READ=1
- };
-
- struct counter_type {
- //Chip IOs;
- bool GATE; //GATE Input value at end of cycle
- bool OUTpin; //OUT output this cycle
-
- //Architected state;
- Bit32u count; //Counter value this cycle
- Bit16u outlatch; //Output latch this cycle
- Bit16u inlatch; //Input latch this cycle
- Bit8u status_latch;
-
- //Status Register data;
- Bit8u rw_mode; //2-bit R/W mode from command word register.
- Bit8u mode; //3-bit mode from command word register.
- bool bcd_mode; //1-bit BCD vs. Binary setting.
- bool null_count; //Null count bit of status register.
-
- //Latch status data;
- bool count_LSB_latched;
- bool count_MSB_latched;
- bool status_latched;
-
- //Miscelaneous State;
- Bit32u count_binary; //Value of the count in binary.
- bool triggerGATE; //Whether we saw GATE rise this cycle.
- rw_status write_state; //Read state this cycle
- rw_status read_state; //Read state this cycle
- bool count_written; //Whether a count written since programmed
- bool first_pass; //Whether or not this is the first loaded count.
- bool state_bit_1; //Miscelaneous state bits.
- bool state_bit_2;
- Bit32u next_change_time; //Next time something besides count changes.
- //0 means never.
- };
-
- counter_type counter[3];
-
- Bit8u controlword;
-
- int seen_problems;
-
- void latch_counter(counter_type & thisctr);
-
- void set_OUT (counter_type & thisctr, bool data);
-
- void set_count (counter_type & thisctr, Bit32u data) BX_CPP_AttrRegparmN(2);
-
- void set_count_to_binary (counter_type & thisctr) BX_CPP_AttrRegparmN(1);
-
- void set_binary_to_count (counter_type & thisctr) BX_CPP_AttrRegparmN(1);
-
- void decrement (counter_type & thisctr) BX_CPP_AttrRegparmN(1);
-
- void decrement_multiple(counter_type & thisctr, Bit32u cycles) BX_CPP_AttrRegparmN(2);
-
- void clock(Bit8u cnum) BX_CPP_AttrRegparmN(1);
-
- void print_counter(counter_type & thisctr);
-
-#ifdef BX_USE_VMX
- void write_initcount_vmx(Bit8u cnum);
-#endif
-
-public:
- void init (void);
- void reset (unsigned type);
- pit_82C54 (void);
-
- void clock_all(Bit32u cycles);
- void clock_multiple(Bit8u cnum, Bit32u cycles);
-
- Bit8u read(Bit8u address);
- void write(Bit8u address, Bit8u data);
-
- void set_GATE(Bit8u cnum, bool data);
- bool read_GATE(Bit8u cnum);
-
- bool read_OUT(Bit8u cnum);
-
- Bit32u get_clock_event_time(Bit8u cnum);
- Bit32u get_next_event_time(void);
-
- void print_cnum(Bit8u cnum);
-
-};
-
-#endif
+++ /dev/null
-////////////////////////////////////////////////////////////////////////
-// $Id: pit_wrap.cc,v 1.52 2003/08/19 00:10:38 cbothamy Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-#include "bochs.h"
-
-#if BX_USE_NEW_PIT
-
-#include "pit_wrap.h"
-
-
-//Important constant #defines:
-#define USEC_PER_SECOND (1000000)
-//1.193181MHz Clock
-#define TICKS_PER_SECOND (1193181)
-
-
-// define a macro to convert floating point numbers into 64-bit integers.
-// In MSVC++ you can convert a 64-bit float into a 64-bit signed integer,
-// but it will not convert a 64-bit float into a 64-bit unsigned integer.
-// This macro works around that.
-#define F2I(x) ((Bit64u)(Bit64s) (x))
-#define I2F(x) ((double)(Bit64s) (x))
-
-//DEBUG configuration:
-
-//Set up Logging.
-#define LOG_THIS bx_pit.
-
-//A single instance.
-bx_pit_c bx_pit;
-#if BX_USE_PIT_SMF
-#define this (&bx_pit)
-#endif
-
-//Workaround for environments where OUT is defined.
-#ifdef OUT
-# undef OUT
-#endif
-
-
-//Generic MAX and MIN Functions
-#define BX_MAX(a,b) ( ((a)>(b))?(a):(b) )
-#define BX_MIN(a,b) ( ((a)>(b))?(b):(a) )
-
-
-//USEC_ALPHA is multiplier for the past.
-//USEC_ALPHA_B is 1-USEC_ALPHA, or multiplier for the present.
-#define USEC_ALPHA ((double)(.8))
-#define USEC_ALPHA_B ((double)(((double)1)-USEC_ALPHA))
-#define USEC_ALPHA2 ((double)(.5))
-#define USEC_ALPHA2_B ((double)(((double)1)-USEC_ALPHA2))
-#define ALPHA_LOWER(old,new) ((Bit64u)((old<new)?((USEC_ALPHA*(I2F(old)))+(USEC_ALPHA_B*(I2F(new)))):((USEC_ALPHA2*(I2F(old)))+(USEC_ALPHA2_B*(I2F(new))))))
-
-
-//PIT tick to usec conversion functions:
-//Direct conversions:
-#define TICKS_TO_USEC(a) ( ((a)*USEC_PER_SECOND)/TICKS_PER_SECOND )
-#define USEC_TO_TICKS(a) ( ((a)*TICKS_PER_SECOND)/USEC_PER_SECOND )
-
-
-bx_pit_c::bx_pit_c( void )
-{
- put("PIT");
- settype(PITLOG);
- s.speaker_data_on=0;
-
- /* 8254 PIT (Programmable Interval Timer) */
-
- BX_PIT_THIS s.timer_handle[1] = BX_NULL_TIMER_HANDLE;
- BX_PIT_THIS s.timer_handle[2] = BX_NULL_TIMER_HANDLE;
- BX_PIT_THIS s.timer_handle[0] = BX_NULL_TIMER_HANDLE;
-}
-
-bx_pit_c::~bx_pit_c( void )
-{
-}
-
- int
-bx_pit_c::init( void )
-{
- DEV_register_irq(0, "8254 PIT");
- DEV_register_ioread_handler(this, read_handler, 0x0040, "8254 PIT", 1);
- DEV_register_ioread_handler(this, read_handler, 0x0041, "8254 PIT", 1);
- DEV_register_ioread_handler(this, read_handler, 0x0042, "8254 PIT", 1);
- DEV_register_ioread_handler(this, read_handler, 0x0043, "8254 PIT", 1);
- DEV_register_ioread_handler(this, read_handler, 0x0061, "8254 PIT", 1);
-
- DEV_register_iowrite_handler(this, write_handler, 0x0040, "8254 PIT", 1);
- DEV_register_iowrite_handler(this, write_handler, 0x0041, "8254 PIT", 1);
- DEV_register_iowrite_handler(this, write_handler, 0x0042, "8254 PIT", 1);
- DEV_register_iowrite_handler(this, write_handler, 0x0043, "8254 PIT", 1);
- DEV_register_iowrite_handler(this, write_handler, 0x0061, "8254 PIT", 1);
-
- BX_DEBUG(("pit: starting init"));
-
- BX_PIT_THIS s.speaker_data_on = 0;
- BX_PIT_THIS s.refresh_clock_div2 = 0;
-
- BX_PIT_THIS s.timer.init();
-
- Bit64u my_time_usec = bx_virt_timer.time_usec();
-
- if (BX_PIT_THIS s.timer_handle[0] == BX_NULL_TIMER_HANDLE) {
- BX_PIT_THIS s.timer_handle[0] = bx_virt_timer.register_timer(this, timer_handler, (unsigned) 100 , 1, 1, "pit_wrap");
- }
- BX_DEBUG(("pit: RESETting timer."));
- bx_virt_timer.deactivate_timer(BX_PIT_THIS s.timer_handle[0]);
- BX_DEBUG(("deactivated timer."));
- if(BX_PIT_THIS s.timer.get_next_event_time()) {
- bx_virt_timer.activate_timer(BX_PIT_THIS s.timer_handle[0],
- (Bit32u)BX_MAX(1,TICKS_TO_USEC(BX_PIT_THIS s.timer.get_next_event_time())),
- 0);
- BX_DEBUG(("activated timer."));
- }
- BX_PIT_THIS s.last_next_event_time = BX_PIT_THIS s.timer.get_next_event_time();
- BX_PIT_THIS s.last_usec=my_time_usec;
-
- BX_PIT_THIS s.total_ticks=0;
- BX_PIT_THIS s.total_usec=0;
-
- BX_DEBUG(("pit: finished init"));
-
- BX_DEBUG(("s.last_usec="FMT_LL"d",BX_PIT_THIS s.last_usec));
- BX_DEBUG(("s.timer_id=%d",BX_PIT_THIS s.timer_handle[0]));
- BX_DEBUG(("s.timer.get_next_event_time=%d",BX_PIT_THIS s.timer.get_next_event_time()));
- BX_DEBUG(("s.last_next_event_time=%d",BX_PIT_THIS s.last_next_event_time));
-
- return(1);
-}
-
- void
-bx_pit_c::reset(unsigned type)
-{
-}
-
-void
-bx_pit_c::timer_handler(void *this_ptr) {
- bx_pit_c * class_ptr = (bx_pit_c *) this_ptr;
-
- class_ptr->handle_timer();
-}
-
-void
-bx_pit_c::handle_timer() {
- Bit64u my_time_usec = bx_virt_timer.time_usec();
- Bit64u time_passed = my_time_usec-BX_PIT_THIS s.last_usec;
- Bit32u time_passed32 = (Bit32u)time_passed;
-
- BX_DEBUG(("pit: entering timer handler"));
-
- if(time_passed32) {
- periodic(time_passed32);
- }
- BX_PIT_THIS s.last_usec=BX_PIT_THIS s.last_usec + time_passed;
- if(time_passed ||
- (BX_PIT_THIS s.last_next_event_time
- != BX_PIT_THIS s.timer.get_next_event_time())
- ) {
- BX_DEBUG(("pit: RESETting timer."));
- bx_virt_timer.deactivate_timer(BX_PIT_THIS s.timer_handle[0]);
- BX_DEBUG(("deactivated timer."));
- if(BX_PIT_THIS s.timer.get_next_event_time()) {
- bx_virt_timer.activate_timer(BX_PIT_THIS s.timer_handle[0],
- (Bit32u)BX_MAX(1,TICKS_TO_USEC(BX_PIT_THIS s.timer.get_next_event_time())),
- 0);
- BX_DEBUG(("activated timer."));
- }
- BX_PIT_THIS s.last_next_event_time = BX_PIT_THIS s.timer.get_next_event_time();
- }
- BX_DEBUG(("s.last_usec="FMT_LL"d",BX_PIT_THIS s.last_usec));
- BX_DEBUG(("s.timer_id=%d",BX_PIT_THIS s.timer_handle[0]));
- BX_DEBUG(("s.timer.get_next_event_time=%x",BX_PIT_THIS s.timer.get_next_event_time()));
- BX_DEBUG(("s.last_next_event_time=%d",BX_PIT_THIS s.last_next_event_time));
-}
-
-
- // static IO port read callback handler
- // redirects to non-static class handler to avoid virtual functions
-
- Bit32u
-bx_pit_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len)
-{
-#if !BX_USE_PIT_SMF
- bx_pit_c *class_ptr = (bx_pit_c *) this_ptr;
-
- return( class_ptr->read(address, io_len) );
-}
-
-
- Bit32u
-bx_pit_c::read( Bit32u address, unsigned int io_len )
-{
-#else
- UNUSED(this_ptr);
-#endif // !BX_USE_PIT_SMF
- BX_DEBUG(("pit: entering read handler"));
-
- handle_timer();
-
- Bit64u my_time_usec = bx_virt_timer.time_usec();
-
- if (bx_dbg.pit)
- BX_INFO(("pit: io read from port %04x", (unsigned) address));
-
- switch (address) {
-
- case 0x40: /* timer 0 - system ticks */
- return(BX_PIT_THIS s.timer.read(0));
- break;
- case 0x41: /* timer 1 read */
- return(BX_PIT_THIS s.timer.read(1));
- break;
- case 0x42: /* timer 2 read */
- return(BX_PIT_THIS s.timer.read(2));
- break;
- case 0x43: /* timer 1 read */
- return(BX_PIT_THIS s.timer.read(3));
- break;
-
- case 0x61:
- /* AT, port 61h */
- BX_PIT_THIS s.refresh_clock_div2 = (bx_bool)((my_time_usec / 15) & 1);
- return( (BX_PIT_THIS s.timer.read_OUT(2)<<5) |
- (BX_PIT_THIS s.refresh_clock_div2<<4) |
- (BX_PIT_THIS s.speaker_data_on<<1) |
- (BX_PIT_THIS s.timer.read_GATE(2)?1:0) );
- break;
-
- default:
- BX_PANIC(("pit: unsupported io read from port %04x", address));
- }
- return(0); /* keep compiler happy */
-}
-
-
- // static IO port write callback handler
- // redirects to non-static class handler to avoid virtual functions
-
- void
-bx_pit_c::write_handler(void *this_ptr, Bit32u address, Bit32u dvalue, unsigned io_len)
-{
-#if !BX_USE_PIT_SMF
- bx_pit_c *class_ptr = (bx_pit_c *) this_ptr;
-
- class_ptr->write(address, dvalue, io_len);
-}
-
- void
-bx_pit_c::write( Bit32u address, Bit32u dvalue,
- unsigned int io_len )
-{
-#else
- UNUSED(this_ptr);
-#endif // !BX_USE_PIT_SMF
- Bit8u value;
- Bit64u my_time_usec = bx_virt_timer.time_usec();
- Bit64u time_passed = my_time_usec-BX_PIT_THIS s.last_usec;
- Bit32u time_passed32 = (Bit32u)time_passed;
-
- BX_DEBUG(("pit: entering write handler"));
-
- if(time_passed32) {
- periodic(time_passed32);
- }
- BX_PIT_THIS s.last_usec=BX_PIT_THIS s.last_usec + time_passed;
-
- value = (Bit8u ) dvalue;
-
- if (bx_dbg.pit)
- BX_INFO(("pit: write to port %04x = %02x",
- (unsigned) address, (unsigned) value));
-
- switch (address) {
- case 0x40: /* timer 0: write count register */
- BX_PIT_THIS s.timer.write(0,value);
- break;
-
- case 0x41: /* timer 1: write count register */
- BX_PIT_THIS s.timer.write( 1,value );
- break;
-
- case 0x42: /* timer 2: write count register */
- BX_PIT_THIS s.timer.write( 2,value );
- break;
-
- case 0x43: /* timer 0-2 mode control */
- BX_PIT_THIS s.timer.write( 3,value );
- break;
-
- case 0x61:
- BX_PIT_THIS s.speaker_data_on = (value >> 1) & 0x01;
-/*??? only on AT+ */
- BX_PIT_THIS s.timer.set_GATE(2, value & 0x01);
-#if BX_CPU_LEVEL < 2
- /* ??? XT: */
- bx_kbd_port61h_write(value);
-#endif
- break;
-
- default:
- BX_PANIC(("pit: unsupported io write to port %04x = %02x",
- (unsigned) address, (unsigned) value));
- }
-
-#ifndef BX_VMX_PIT
- if ((BX_PIT_THIS s.timer.read_OUT(0))==1) {
- DEV_pic_raise_irq(0);
- } else {
- DEV_pic_lower_irq(0);
- }
-#endif
-
- if(time_passed ||
- (BX_PIT_THIS s.last_next_event_time
- != BX_PIT_THIS s.timer.get_next_event_time())
- ) {
- BX_DEBUG(("pit: RESETting timer."));
- bx_virt_timer.deactivate_timer(BX_PIT_THIS s.timer_handle[0]);
- BX_DEBUG(("deactivated timer."));
- if(BX_PIT_THIS s.timer.get_next_event_time()) {
- bx_virt_timer.activate_timer(BX_PIT_THIS s.timer_handle[0],
- (Bit32u)BX_MAX(1,TICKS_TO_USEC(BX_PIT_THIS s.timer.get_next_event_time())),
- 0);
- BX_DEBUG(("activated timer."));
- }
- BX_PIT_THIS s.last_next_event_time = BX_PIT_THIS s.timer.get_next_event_time();
- }
- BX_DEBUG(("s.last_usec="FMT_LL"d",BX_PIT_THIS s.last_usec));
- BX_DEBUG(("s.timer_id=%d",BX_PIT_THIS s.timer_handle[0]));
- BX_DEBUG(("s.timer.get_next_event_time=%x",BX_PIT_THIS s.timer.get_next_event_time()));
- BX_DEBUG(("s.last_next_event_time=%d",BX_PIT_THIS s.last_next_event_time));
-
-}
-
-
-
-
- int
-bx_pit_c::SaveState( class state_file *fd )
-{
- fd->write_check ("8254 start");
- fd->write (&BX_PIT_THIS s, sizeof (BX_PIT_THIS s));
- fd->write_check ("8254 end");
- return(0);
-}
-
-
- int
-bx_pit_c::LoadState( class state_file *fd )
-{
- fd->read_check ("8254 start");
- fd->read (&BX_PIT_THIS s, sizeof (BX_PIT_THIS s));
- fd->read_check ("8254 end");
- return(0);
-}
-
-
-#if 0
- void
-bx_kbd_port61h_write(Bit8u value)
-{
-// PcError("KBD_PORT61H_WRITE(): not implemented yet");
- UNUSED( value );
-}
-#endif
-
-
- bx_bool
-bx_pit_c::periodic( Bit32u usec_delta )
-{
- bx_bool prev_timer0_out = BX_PIT_THIS s.timer.read_OUT(0);
- bx_bool want_interrupt = 0;
- Bit32u ticks_delta = 0;
-
-#ifdef BX_SCHEDULED_DIE_TIME
- if (bx_pc_system.time_ticks() > BX_SCHEDULED_DIE_TIME) {
- BX_ERROR (("ticks exceeded scheduled die time, quitting"));
- BX_EXIT (2);
- }
-#endif
-
- BX_PIT_THIS s.total_usec += usec_delta;
- ticks_delta=(Bit32u)((USEC_TO_TICKS((Bit64u)(BX_PIT_THIS s.total_usec)))-BX_PIT_THIS s.total_ticks);
- BX_PIT_THIS s.total_ticks += ticks_delta;
-
- while ((BX_PIT_THIS s.total_ticks >= TICKS_PER_SECOND) && (BX_PIT_THIS s.total_usec >= USEC_PER_SECOND)) {
- BX_PIT_THIS s.total_ticks -= TICKS_PER_SECOND;
- BX_PIT_THIS s.total_usec -= USEC_PER_SECOND;
- }
-
- while(ticks_delta>0) {
- Bit32u maxchange=BX_PIT_THIS s.timer.get_next_event_time();
- Bit32u timedelta=maxchange;
- if((maxchange==0) || (maxchange>ticks_delta)) {
- timedelta=ticks_delta;
- }
- BX_PIT_THIS s.timer.clock_all(timedelta);
- if ( (prev_timer0_out==0) ) {
- if ((BX_PIT_THIS s.timer.read_OUT(0))==1) {
-#ifndef BX_VMX_PIT
- DEV_pic_raise_irq(0);
-#endif
- prev_timer0_out=1;
- }
- } else {
- if ((BX_PIT_THIS s.timer.read_OUT(0))==0) {
-#ifndef BX_VMX_PIT
- DEV_pic_lower_irq(0);
-#endif
- prev_timer0_out=0;
- }
- }
- prev_timer0_out=BX_PIT_THIS s.timer.read_OUT(0);
- ticks_delta-=timedelta;
- }
-
- return(want_interrupt);
-}
-
-#endif // #if BX_USE_NEW_PIT
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: pit_wrap.h,v 1.17 2003/08/19 00:10:38 cbothamy Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2001 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-#ifndef _BX_PIT_WRAP_H
-#define _BX_PIT_WRAP_H
-
-#include "bochs.h"
-
-#if BX_USE_NEW_PIT
-
-#include "pit82c54.h"
-
-#if BX_USE_PIT_SMF
-# define BX_PIT_SMF static
-# define BX_PIT_THIS bx_pit.
-#else
-# define BX_PIT_SMF
-# define BX_PIT_THIS this->
-#endif
-
-#ifdef OUT
-# undef OUT
-#endif
-
-class bx_pit_c : public logfunctions {
-public:
- bx_pit_c( void );
- ~bx_pit_c( void );
- BX_PIT_SMF int init( void );
- BX_PIT_SMF void reset( unsigned type);
- BX_PIT_SMF bx_bool periodic( Bit32u usec_delta );
-
- BX_PIT_SMF int SaveState( class state_file *fd );
- BX_PIT_SMF int LoadState( class state_file *fd );
-
-private:
-
- static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len);
- static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len);
-#if !BX_USE_PIT_SMF
- Bit32u read( Bit32u addr, unsigned int len );
- void write( Bit32u addr, Bit32u Value, unsigned int len );
-#endif
-
- struct s_type {
- pit_82C54 timer;
- Bit8u speaker_data_on;
- bx_bool refresh_clock_div2;
- int timer_handle[3];
- Bit64u last_usec;
- Bit32u last_next_event_time;
- Bit64u total_ticks;
- Bit64u usec_per_second;
- Bit64u ticks_per_second;
- Bit64u total_sec;
- Bit64u last_time;
- Bit64u last_sec_usec;
- Bit64u max_ticks;
- Bit64u stored_delta;
- Bit64u total_usec;
- Bit64u em_last_realtime;
- Bit64u last_realtime_delta;
- Bit64u last_realtime_ticks;
- } s;
-
- static void timer_handler(void *this_ptr);
- BX_PIT_SMF void handle_timer();
-
- BX_PIT_SMF void write_count_reg( Bit8u value, unsigned timerid );
- BX_PIT_SMF Bit8u read_counter( unsigned timerid );
- BX_PIT_SMF void latch( unsigned timerid );
- BX_PIT_SMF void set_GATE(unsigned pit_id, unsigned value);
- BX_PIT_SMF void start(unsigned timerid);
-
- BX_PIT_SMF void second_update_data(void);
-};
-
-extern bx_pit_c bx_pit;
-
-#endif // #if BX_USE_NEW_PIT
-#endif // #ifndef _BX_PIT_WRAP_H
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: plugin.cc,v 1.8 2003/07/31 12:04:47 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// This file defines the plugin and plugin-device registration functions and
-// the device registration functions. It handles dynamic loading of modules,
-// using the LTDL library for cross-platform support.
-//
-// This file is based on the plugin.c file from plex86, but with significant
-// changes to make it work in Bochs.
-// Plex86 is Copyright (C) 1999-2000 The plex86 developers team
-//
-/////////////////////////////////////////////////////////////////////////
-
-#include "bochs.h"
-#include "plugin.h"
-
-#define LOG_THIS genlog->
-
-#define PLUGIN_INIT_FMT_STRING "lib%s_LTX_plugin_init"
-#define PLUGIN_FINI_FMT_STRING "lib%s_LTX_plugin_fini"
-#define PLUGIN_PATH ""
-
-#ifndef WIN32
-#define PLUGIN_FILENAME_FORMAT "libbx_%s.la"
-#else
-#define PLUGIN_FILENAME_FORMAT "bx_%s.dll"
-#endif
-
-
-
-void (*pluginRegisterIRQ)(unsigned irq, const char* name) = 0;
-void (*pluginUnregisterIRQ)(unsigned irq, const char* name) = 0;
-
-void (* pluginResetSignal)(unsigned sig) = 0;
-
-void (*pluginSetHRQ)(unsigned val) = 0;
-void (*pluginSetHRQHackCallback)( void (*callback)(void) ) = 0;
-
-int (*pluginRegisterIOReadHandler)(void *thisPtr, ioReadHandler_t callback,
- unsigned base, const char *name, Bit8u mask) = 0;
-int (*pluginRegisterIOWriteHandler)(void *thisPtr, ioWriteHandler_t callback,
- unsigned base, const char *name, Bit8u mask) = 0;
-int (*pluginRegisterDefaultIOReadHandler)(void *thisPtr, ioReadHandler_t callback,
- const char *name, Bit8u mask) = 0;
-int (*pluginRegisterDefaultIOWriteHandler)(void *thisPtr, ioWriteHandler_t callback,
- const char *name, Bit8u mask) = 0;
-int (*pluginRegisterTimer)(void *this_ptr, void (*funct)(void *),
- Bit32u useconds, bx_bool continuous,
- bx_bool active, const char* name) = 0;
-void (*pluginActivateTimer)(unsigned id, Bit32u usec, bx_bool continuous) = 0;
-
-void (*pluginHRQHackCallback)(void);
-unsigned pluginHRQ = 0;
-
-plugin_t *plugins = NULL; /* Head of the linked list of plugins */
-#if BX_PLUGINS
-static void plugin_init_one(plugin_t *plugin);
-#endif
-
-device_t *devices = NULL; /* Head of the linked list of registered devices */
-
-plugin_t *current_plugin_context = NULL;
-
-/************************************************************************/
-/* Builtins declarations */
-/************************************************************************/
-
- static void
-builtinRegisterIRQ(unsigned irq, const char* name)
-{
-#if 0
- pluginlog->panic("builtinRegisterIRQ called, no pic plugin loaded?");
-#else
- bx_devices.register_irq(irq, name);
-#endif
-}
-
- static void
-builtinUnregisterIRQ(unsigned irq, const char* name)
-{
-#if 0
- pluginlog->panic("builtinUnregisterIRQ called, no pic plugin loaded?");
-#else
- bx_devices.unregister_irq(irq, name);
-#endif
-}
-
- static void
-builtinSetHRQ(unsigned val)
-{
-#if 0
- pluginlog->panic("builtinSetHRQ called, no plugin loaded?");
-#else
- pluginHRQ = val;
-#endif
-}
-
- static void
-builtinSetHRQHackCallback( void (*callback)(void) )
-{
-#if 0
- pluginlog->panic("builtinSetHRQHackCallback called, no plugin loaded?");
-#else
- pluginHRQHackCallback = callback;
-#endif
-}
-
- static void
-builtinResetSignal( unsigned )
-{
- pluginlog->panic("builtinResetSignal called, no plugin loaded?");
-}
-
- static int
-builtinRegisterIOReadHandler(void *thisPtr, ioReadHandler_t callback,
- unsigned base, const char *name, Bit8u mask)
-{
- BX_ASSERT (mask<8);
- bx_devices.register_io_read_handler (thisPtr, callback, base, name, mask);
- pluginlog->ldebug("plugin %s registered I/O read address at %04x", name, base);
- return 0;
-}
-
- static int
-builtinRegisterIOWriteHandler(void *thisPtr, ioWriteHandler_t callback,
- unsigned base, const char *name, Bit8u mask)
-{
- BX_ASSERT (mask<8);
- bx_devices.register_io_write_handler (thisPtr, callback, base, name, mask);
- pluginlog->ldebug("plugin %s registered I/O write address at %04x", name, base);
- return 0;
-}
-
- static int
-builtinRegisterDefaultIOReadHandler(void *thisPtr, ioReadHandler_t callback,
- const char *name, Bit8u mask)
-{
- BX_ASSERT (mask<8);
- bx_devices.register_default_io_read_handler (thisPtr, callback, name, mask);
- pluginlog->ldebug("plugin %s registered default I/O read ", name);
- return 0;
-}
-
- static int
-builtinRegisterDefaultIOWriteHandler(void *thisPtr, ioWriteHandler_t callback,
- const char *name, Bit8u mask)
-{
- BX_ASSERT (mask<8);
- bx_devices.register_default_io_write_handler (thisPtr, callback, name, mask);
- pluginlog->ldebug("plugin %s registered default I/O write ", name);
- return 0;
-}
-
- static int
-builtinRegisterTimer(void *this_ptr, void (*funct)(void *),
- Bit32u useconds, bx_bool continuous,
- bx_bool active, const char* name)
-{
- int id = bx_pc_system.register_timer (this_ptr, funct, useconds, continuous, active, name);
- pluginlog->ldebug("plugin %s registered timer %d", name, id);
- return id;
-}
-
- static void
-builtinActivateTimer(unsigned id, Bit32u usec, bx_bool continuous)
-{
- bx_pc_system.activate_timer (id, usec, continuous);
- pluginlog->ldebug("plugin activated timer %d", id);
-}
-
-#if BX_PLUGINS
-/************************************************************************/
-/* Plugin initialization / deinitialization */
-/************************************************************************/
-
- void
-plugin_init_all (void)
-{
- plugin_t *plugin;
-
- pluginlog->info("Initializing plugins");
-
- for (plugin = plugins; plugin; plugin = plugin->next)
- {
- char *arg_ptr = plugin->args;
-
- /* process the command line */
- plugin->argc = 0;
- while (plugin->argc < MAX_ARGC)
- {
- while (*arg_ptr && isspace (*arg_ptr))
- arg_ptr++;
-
- if (!*arg_ptr)
- break;
- plugin->argv[plugin->argc++] = arg_ptr;
-
- while (*arg_ptr && !isspace (*arg_ptr))
- arg_ptr++;
-
- if (!*arg_ptr)
- break;
- *arg_ptr++ = '\0';
- }
-
- /* initialize the plugin */
- if (plugin->plugin_init (plugin, plugin->type, plugin->argc, plugin->argv))
- {
- pluginlog->panic("Plugin initialization failed for %s", plugin->name);
- plugin_abort();
- }
-
- plugin->initialized = 1;
- }
-
- return;
-}
-
-void
-plugin_init_one(plugin_t *plugin)
-{
- char *arg_ptr = plugin->args;
-
- /* process the command line */
- plugin->argc = 0;
- while (plugin->argc < MAX_ARGC)
- {
- while (*arg_ptr && isspace (*arg_ptr))
- arg_ptr++;
-
- if (!*arg_ptr)
- break;
- plugin->argv[plugin->argc++] = arg_ptr;
-
- while (*arg_ptr && !isspace (*arg_ptr))
- arg_ptr++;
-
- if (!*arg_ptr)
- break;
- *arg_ptr++ = '\0';
- }
-
- /* initialize the plugin */
- if (plugin->plugin_init (plugin, plugin->type, plugin->argc, plugin->argv))
- {
- pluginlog->info("Plugin initialization failed for %s", plugin->name);
- plugin_abort();
- }
-
- plugin->initialized = 1;
-}
-
-
- plugin_t *
-plugin_unload(plugin_t *plugin)
-{
- plugin_t *dead_plug;
-
- if (plugin->initialized)
- plugin->plugin_fini ();
-
- lt_dlclose (plugin->handle);
- free (plugin->name);
- free (plugin->args);
-
- dead_plug = plugin;
- plugin = plugin->next;
- free (dead_plug);
-
- return plugin;
-}
-
-
-void
-plugin_fini_all (void)
-{
- plugin_t *plugin;
-
- for (plugin = plugins; plugin; plugin = plugin_unload (plugin));
-
- return;
-}
-
- void
-plugin_load (char *name, char *args, plugintype_t type)
-{
- plugin_t *plugin;
-
- plugin = (plugin_t *)malloc (sizeof (plugin_t));
- if (!plugin)
- {
- BX_PANIC (("malloc plugin_t failed"));
- }
-
- plugin->type = type;
- plugin->name = name;
- plugin->args = args;
- plugin->initialized = 0;
-
- char plugin_filename[BX_PATHNAME_LEN], buf[BX_PATHNAME_LEN];
- sprintf (buf, PLUGIN_FILENAME_FORMAT, name);
- sprintf(plugin_filename, "%s%s", PLUGIN_PATH, buf);
-
- // Set context so that any devices that the plugin registers will
- // be able to see which plugin created them. The registration will
- // be called from either dlopen (global constructors) or plugin_init.
- BX_ASSERT (current_plugin_context == NULL);
- current_plugin_context = plugin;
- plugin->handle = lt_dlopen (plugin_filename);
- BX_INFO (("lt_dlhandle is %p", plugin->handle));
- if (!plugin->handle)
- {
- current_plugin_context = NULL;
- BX_PANIC (("dlopen failed for module '%s': %s", name, lt_dlerror ()));
- free (plugin);
- return;
- }
-
- sprintf (buf, PLUGIN_INIT_FMT_STRING, name);
- plugin->plugin_init =
- (int (*)(struct _plugin_t *, enum plugintype_t, int, char *[])) /* monster typecast */
- lt_dlsym (plugin->handle, buf);
- if (plugin->plugin_init == NULL) {
- pluginlog->panic("could not find plugin_init: %s", lt_dlerror ());
- plugin_abort ();
- }
-
- sprintf (buf, PLUGIN_FINI_FMT_STRING, name);
- plugin->plugin_fini = (void (*)(void)) lt_dlsym (plugin->handle, buf);
- if (plugin->plugin_init == NULL) {
- pluginlog->panic("could not find plugin_fini: %s", lt_dlerror ());
- plugin_abort ();
- }
- pluginlog->info("loaded plugin %s",plugin_filename);
-
-
- /* Insert plugin at the _end_ of the plugin linked list. */
- plugin->next = NULL;
-
- if (!plugins)
- {
- /* Empty list, this become the first entry. */
- plugins = plugin;
- }
- else
- {
- /* Non-empty list. Add to end. */
- plugin_t *temp = plugins;
-
- while (temp->next)
- temp = temp->next;
-
- temp->next = plugin;
- }
-
- plugin_init_one(plugin);
-
- // check that context didn't change. This should only happen if we
- // need a reentrant plugin_load.
- BX_ASSERT (current_plugin_context == plugin);
- current_plugin_context = NULL;
-
- return;
-}
-
-void
-plugin_abort (void)
-{
- pluginlog->panic("plugin load aborted");
-}
-
-#endif /* end of #if BX_PLUGINS */
-
-/************************************************************************/
-/* Plugin system: initialisation of plugins entry points */
-/************************************************************************/
-
- void
-plugin_startup(void)
-{
- pluginRegisterIRQ = builtinRegisterIRQ;
- pluginUnregisterIRQ = builtinUnregisterIRQ;
-
- pluginResetSignal = builtinResetSignal;
-
- pluginSetHRQHackCallback = builtinSetHRQHackCallback;
- pluginSetHRQ = builtinSetHRQ;
-
- pluginRegisterIOReadHandler = builtinRegisterIOReadHandler;
- pluginRegisterIOWriteHandler = builtinRegisterIOWriteHandler;
-
- pluginRegisterDefaultIOReadHandler = builtinRegisterDefaultIOReadHandler;
- pluginRegisterDefaultIOWriteHandler = builtinRegisterDefaultIOWriteHandler;
-
- pluginRegisterTimer = builtinRegisterTimer;
- pluginActivateTimer = builtinActivateTimer;
-
-#if BX_PLUGINS
- pluginlog = new logfunctions();
- pluginlog->put("PLGIN");
- pluginlog->settype(PLUGINLOG);
- int status = lt_dlinit ();
- if (status != 0) {
- BX_ERROR (("initialization error in ltdl library (for loading plugins)"));
- BX_PANIC (("error message was: %s", lt_dlerror ()));
- }
-#endif
-}
-
-
-/************************************************************************/
-/* Plugin system: Device registration */
-/************************************************************************/
-
-void pluginRegisterDeviceDevmodel(plugin_t *plugin, plugintype_t type, bx_devmodel_c *devmodel, char *name)
-{
- device_t *device;
-
- device = (device_t *)malloc (sizeof (device_t));
- if (!device)
- {
- pluginlog->panic("can't allocate device_t");
- }
-
- device->name = name;
- BX_ASSERT (devmodel != NULL);
- device->devmodel = devmodel;
- device->plugin = plugin; // this can be NULL
- device->use_devmodel_interface = 1;
- device->device_init_mem = NULL; // maybe should use 1 to detect any use?
- device->device_init_dev = NULL;
- device->device_reset = NULL;
- device->device_load_state = NULL;
- device->device_save_state = NULL;
- device->next = NULL;
-
- // Don't add every kind of device to the list.
- switch (type) {
- case PLUGTYPE_CORE:
- // Core devices are present whether or not we are using plugins, so
- // they are managed by the same code in iodev/devices.cc whether
- // plugins are on or off.
- return; // Do not add core devices to the devices list.
- case PLUGTYPE_OPTIONAL:
- case PLUGTYPE_USER:
- default:
- // The plugin system will manage optional and user devices only.
- break;
- }
-
- if (!devices)
- {
- /* Empty list, this become the first entry. */
- devices = device;
- }
- else
- {
- /* Non-empty list. Add to end. */
- device_t *temp = devices;
-
- while (temp->next)
- temp = temp->next;
-
- temp->next = device;
- }
-}
-
-/************************************************************************/
-/* Plugin system: Check if a plugin is loaded */
-/************************************************************************/
-
-bx_bool pluginDevicePresent(char *name)
-{
- device_t *device;
-
- for (device = devices; device; device = device->next)
- {
- if (strcmp(device->name,name)==0) return true;
- }
-
- return false;
-}
-
-#if BX_PLUGINS
-/************************************************************************/
-/* Plugin system: Load one plugin */
-/************************************************************************/
-
-int bx_load_plugin (const char *name, plugintype_t type)
-{
- char *namecopy = new char[1+strlen(name)];
- strcpy (namecopy, name);
- plugin_load (namecopy, "", type);
- return 0;
-}
-#endif /* end of #if BX_PLUGINS */
-
-/*************************************************************************/
-/* Plugin system: Execute init function of all registered plugin-devices */
-/*************************************************************************/
-
-void bx_init_plugins()
-{
- device_t *device;
-
- // two loops
- for (device = devices; device; device = device->next)
- {
- if (!device->use_devmodel_interface) {
- if (device->device_init_mem != NULL) {
- pluginlog->info("init_mem of '%s' plugin device by function pointer",device->name);
- device->device_init_mem(BX_MEM(0));
- }
- } else {
- pluginlog->info("init_mem of '%s' plugin device by virtual method",device->name);
- device->devmodel->init_mem (BX_MEM(0));
- }
- }
-
- for (device = devices; device; device = device->next)
- {
- if (!device->use_devmodel_interface) {
- if (device->device_init_dev != NULL) {
- pluginlog->info("init_dev of '%s' plugin device by function pointer",device->name);
- device->device_init_dev();
- }
- } else {
- pluginlog->info("init_dev of '%s' plugin device by virtual method",device->name);
- device->devmodel->init ();
- }
- }
-}
-
-/**************************************************************************/
-/* Plugin system: Execute reset function of all registered plugin-devices */
-/**************************************************************************/
-
-void bx_reset_plugins(unsigned signal)
-{
- device_t *device;
- for (device = devices; device; device = device->next)
- {
- if (!device->use_devmodel_interface) {
- if (device->device_reset != NULL) {
- pluginlog->info("reset of '%s' plugin device by function pointer",device->name);
- device->device_reset(signal);
- }
- } else {
- pluginlog->info("reset of '%s' plugin device by virtual method",device->name);
- device->devmodel->reset (signal);
- }
- }
-}
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: scancodes.cc,v 1.5 2002/10/24 21:07:51 bdenney Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-// Define BX_PLUGGABLE in files that can be compiled into plugins. For
-// platforms that require a special tag on exported symbols, BX_PLUGGABLE
-// is used to know when we are exporting symbols and when we are importing.
-#define BX_PLUGGABLE
-
-#include "bochs.h"
-#include "scancodes.h"
-
-unsigned char translation8042[256] = {
- 0xff,0x43,0x41,0x3f,0x3d,0x3b,0x3c,0x58,0x64,0x44,0x42,0x40,0x3e,0x0f,0x29,0x59,
- 0x65,0x38,0x2a,0x70,0x1d,0x10,0x02,0x5a,0x66,0x71,0x2c,0x1f,0x1e,0x11,0x03,0x5b,
- 0x67,0x2e,0x2d,0x20,0x12,0x05,0x04,0x5c,0x68,0x39,0x2f,0x21,0x14,0x13,0x06,0x5d,
- 0x69,0x31,0x30,0x23,0x22,0x15,0x07,0x5e,0x6a,0x72,0x32,0x24,0x16,0x08,0x09,0x5f,
- 0x6b,0x33,0x25,0x17,0x18,0x0b,0x0a,0x60,0x6c,0x34,0x35,0x26,0x27,0x19,0x0c,0x61,
- 0x6d,0x73,0x28,0x74,0x1a,0x0d,0x62,0x6e,0x3a,0x36,0x1c,0x1b,0x75,0x2b,0x63,0x76,
- 0x55,0x56,0x77,0x78,0x79,0x7a,0x0e,0x7b,0x7c,0x4f,0x7d,0x4b,0x47,0x7e,0x7f,0x6f,
- 0x52,0x53,0x50,0x4c,0x4d,0x48,0x01,0x45,0x57,0x4e,0x51,0x4a,0x37,0x49,0x46,0x54,
- 0x80,0x81,0x82,0x41,0x54,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f,
- 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f,
- 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
- 0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbf,
- 0xc0,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc7,0xc8,0xc9,0xca,0xcb,0xcc,0xcd,0xce,0xcf,
- 0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,
- 0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,
- 0xf0,0xf1,0xf2,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfd,0xfe,0xff
- };
-
-
-// Definition of scancodes make and break,
-// for each set (mf1/xt , mf2/at , mf3/ps2)
-// The table must be in BX_KEY order
-//
-scancode scancodes[BX_KEY_NBKEYS][3] =
-{
- { // BX_KEY_CTRL_L ( ibm 58)
- { "\x1D" , "\x9D" },
- { "\x14" , "\xF0\x14" },
- { "\x11" , "\xF0\x11" },
- },
-
- { // BX_KEY_SHIFT_L ( ibm 44)
- { "\x2A" , "\xAA" },
- { "\x12" , "\xF0\x12" },
- { "\x12" , "\xF0\x12" },
- },
-
- { // BX_KEY_F1 ( ibm 112 )
- { "\x3B" , "\xBB" },
- { "\x05" , "\xF0\x05" },
- { "\x07" , "\xF0\x07" },
- },
-
- { // BX_KEY_F2 ( ibm 113 )
- { "\x3C" , "\xBC" },
- { "\x06" , "\xF0\x06" },
- { "\x0F" , "\xF0\x0F" },
- },
-
- { // BX_KEY_F3 ( ibm 114 )
- { "\x3D" , "\xBD" },
- { "\x04" , "\xF0\x04" },
- { "\x17" , "\xF0\x17" },
- },
-
- { // BX_KEY_F4 ( ibm 115 )
- { "\x3E" , "\xBE" },
- { "\x0C" , "\xF0\x0C" },
- { "\x1F" , "\xF0\x1F" },
- },
-
- { // BX_KEY_F5 ( ibm 116 )
- { "\x3F" , "\xBF" },
- { "\x03" , "\xF0\x03" },
- { "\x27" , "\xF0\x27" },
- },
-
- { // BX_KEY_F6 ( ibm 117 )
- { "\x40" , "\xC0" },
- { "\x0B" , "\xF0\x0B" },
- { "\x2F" , "\xF0\x2F" },
- },
-
- { // BX_KEY_F7 ( ibm 118 )
- { "\x41" , "\xC1" },
- { "\x83" , "\xF0\x83" },
- { "\x37" , "\xF0\x37" },
-},
-
- { // BX_KEY_F8 ( ibm 119 )
- { "\x42" , "\xC2" },
- { "\x0A" , "\xF0\x0A" },
- { "\x3F" , "\xF0\x3F" },
- },
-
- { // BX_KEY_F9 ( ibm 120 )
- { "\x43" , "\xC3" },
- { "\x01" , "\xF0\x01" },
- { "\x47" , "\xF0\x47" },
- },
-
- { // BX_KEY_F10 ( ibm 121 )
- { "\x44" , "\xC4" },
- { "\x09" , "\xF0\x09" },
- { "\x4F" , "\xF0\x4F" },
- },
-
- { // BX_KEY_F11 ( ibm 122 )
- { "\x57" , "\xD7" },
- { "\x78" , "\xF0\x78" },
- { "\x56" , "\xF0\x56" },
- },
-
- { // BX_KEY_F12 ( ibm 123 )
- { "\x58" , "\xD8" },
- { "\x07" , "\xF0\x07" },
- { "\x5E" , "\xF0\x5E" },
- },
-
- { // BX_KEY_CTRL_R ( ibm 64 )
- { "\xE0\x1D" , "\xE0\x9D" },
- { "\xE0\x14" , "\xE0\xF0\x14" },
- { "\x58" , "\xF0x58" },
- },
-
- { // BX_KEY_SHIFT_R ( ibm 57 )
- { "\x36" , "\xB6" },
- { "\x59" , "\xF0\x59" },
- { "\x59" , "\xF0\x59" },
- },
-
- { // BX_KEY_CAPS_LOCK ( ibm 30 )
- { "\x3A" , "\xBA" },
- { "\x58" , "\xF0\x58" },
- { "\x14" , "\xF0\x14" },
- },
-
- { // BX_KEY_NUM_LOCK ( ibm 90 )
- { "\x45" , "\xC5" },
- { "\x77" , "\xF0\x77" },
- { "\x76" , "\xF0\x76" },
- },
-
- { // BX_KEY_ALT_L ( ibm 60 )
- { "\x38" , "\xB8" },
- { "\x11" , "\xF0\x11" },
- { "\x19" , "\xF0\x19" },
- },
-
- { // BX_KEY_ALT_R ( ibm 62 )
- { "\xE0\x38" , "\xE0\xB8" },
- { "\xE0\x11" , "\xE0\xF0\x11" },
- { "\x39" , "\xF0\x39" },
- },
-
- { // BX_KEY_A ( ibm 31 )
- { "\x1E" , "\x9E" },
- { "\x1C" , "\xF0\x1C" },
- { "\x1C" , "\xF0\x1C" },
- },
-
- { // BX_KEY_B ( ibm 50 )
- { "\x30" , "\xB0" },
- { "\x32" , "\xF0\x32" },
- { "\x32" , "\xF0\x32" },
- },
-
- { // BX_KEY_C ( ibm 48 )
- { "\x2E" , "\xAE" },
- { "\x21" , "\xF0\x21" },
- { "\x21" , "\xF0\x21" },
- },
-
- { // BX_KEY_D ( ibm 33 )
- { "\x20" , "\xA0" },
- { "\x23" , "\xF0\x23" },
- { "\x23" , "\xF0\x23" },
- },
-
- { // BX_KEY_E ( ibm 19 )
- { "\x12" , "\x92" },
- { "\x24" , "\xF0\x24" },
- { "\x24" , "\xF0\x24" },
- },
-
- { // BX_KEY_F ( ibm 34 )
- { "\x21" , "\xA1" },
- { "\x2B" , "\xF0\x2B" },
- { "\x2B" , "\xF0\x2B" },
- },
-
- { // BX_KEY_G ( ibm 35 )
- { "\x22" , "\xA2" },
- { "\x34" , "\xF0\x34" },
- { "\x34" , "\xF0\x34" },
- },
-
- { // BX_KEY_H ( ibm 36 )
- { "\x23" , "\xA3" },
- { "\x33" , "\xF0\x33" },
- { "\x33" , "\xF0\x33" },
- },
-
- { // BX_KEY_I ( ibm 24 )
- { "\x17" , "\x97" },
- { "\x43" , "\xF0\x43" },
- { "\x43" , "\xF0\x43" },
- },
-
- { // BX_KEY_J ( ibm 37 )
- { "\x24" , "\xA4" },
- { "\x3B" , "\xF0\x3B" },
- { "\x3B" , "\xF0\x3B" },
- },
-
- { // BX_KEY_K ( ibm 38 )
- { "\x25" , "\xA5" },
- { "\x42" , "\xF0\x42" },
- { "\x42" , "\xF0\x42" },
- },
-
- { // BX_KEY_L ( ibm 39 )
- { "\x26" , "\xA6" },
- { "\x4B" , "\xF0\x4B" },
- { "\x4B" , "\xF0\x4B" },
- },
-
- { // BX_KEY_M ( ibm 52 )
- { "\x32" , "\xB2" },
- { "\x3A" , "\xF0\x3A" },
- { "\x3A" , "\xF0\x3A" },
- },
-
- { // BX_KEY_N ( ibm 51 )
- { "\x31" , "\xB1" },
- { "\x31" , "\xF0\x31" },
- { "\x31" , "\xF0\x31" },
- },
-
- { // BX_KEY_O ( ibm 25 )
- { "\x18" , "\x98" },
- { "\x44" , "\xF0\x44" },
- { "\x44" , "\xF0\x44" },
- },
-
- { // BX_KEY_P ( ibm 26 )
- { "\x19" , "\x99" },
- { "\x4D" , "\xF0\x4D" },
- { "\x4D" , "\xF0\x4D" },
- },
-
- { // BX_KEY_Q ( ibm 17 )
- { "\x10" , "\x90" },
- { "\x15" , "\xF0\x15" },
- { "\x15" , "\xF0\x15" },
- },
-
- { // BX_KEY_R ( ibm 20 )
- { "\x13" , "\x93" },
- { "\x2D" , "\xF0\x2D" },
- { "\x2D" , "\xF0\x2D" },
- },
-
- { // BX_KEY_S ( ibm 32 )
- { "\x1F" , "\x9F" },
- { "\x1B" , "\xF0\x1B" },
- { "\x1B" , "\xF0\x1B" },
- },
-
- { // BX_KEY_T ( ibm 21 )
- { "\x14" , "\x94" },
- { "\x2C" , "\xF0\x2C" },
- { "\x2C" , "\xF0\x2C" },
- },
-
- { // BX_KEY_U ( ibm 23 )
- { "\x16" , "\x96" },
- { "\x3C" , "\xF0\x3C" },
- { "\x3C" , "\xF0\x3C" },
- },
-
- { // BX_KEY_V ( ibm 49 )
- { "\x2F" , "\xAF" },
- { "\x2A" , "\xF0\x2A" },
- { "\x2A" , "\xF0\x2A" },
- },
-
- { // BX_KEY_W ( ibm 18 )
- { "\x11" , "\x91" },
- { "\x1D" , "\xF0\x1D" },
- { "\x1D" , "\xF0\x1D" },
- },
-
- { // BX_KEY_X ( ibm 47 )
- { "\x2D" , "\xAD" },
- { "\x22" , "\xF0\x22" },
- { "\x22" , "\xF0\x22" },
- },
-
- { // BX_KEY_Y ( ibm 22 )
- { "\x15" , "\x95" },
- { "\x35" , "\xF0\x35" },
- { "\x35" , "\xF0\x35" },
- },
-
- { // BX_KEY_Z ( ibm 46 )
- { "\x2C" , "\xAC" },
- { "\x1A" , "\xF0\x1A" },
- { "\x1A" , "\xF0\x1A" },
- },
-
- { // BX_KEY_0 ( ibm 11 )
- { "\x0B" , "\x8B" },
- { "\x45" , "\xF0\x45" },
- { "\x45" , "\xF0\x45" },
- },
-
- { // BX_KEY_1 ( ibm 2 )
- { "\x02" , "\x82" },
- { "\x16" , "\xF0\x16" },
- { "\x16" , "\xF0\x16" },
- },
-
- { // BX_KEY_2 ( ibm 3 )
- { "\x03" , "\x83" },
- { "\x1E" , "\xF0\x1E" },
- { "\x1E" , "\xF0\x1E" },
- },
-
- { // BX_KEY_3 ( ibm 4 )
- { "\x04" , "\x84" },
- { "\x26" , "\xF0\x26" },
- { "\x26" , "\xF0\x26" },
- },
-
- { // BX_KEY_4 ( ibm 5 )
- { "\x05" , "\x85" },
- { "\x25" , "\xF0\x25" },
- { "\x25" , "\xF0\x25" },
- },
-
- { // BX_KEY_5 ( ibm 6 )
- { "\x06" , "\x86" },
- { "\x2E" , "\xF0\x2E" },
- { "\x2E" , "\xF0\x2E" },
- },
-
- { // BX_KEY_6 ( ibm 7 )
- { "\x07" , "\x87" },
- { "\x36" , "\xF0\x36" },
- { "\x36" , "\xF0\x36" },
- },
-
- { // BX_KEY_7 ( ibm 8 )
- { "\x08" , "\x88" },
- { "\x3D" , "\xF0\x3D" },
- { "\x3D" , "\xF0\x3D" },
- },
-
- { // BX_KEY_8 ( ibm 9 )
- { "\x09" , "\x89" },
- { "\x3E" , "\xF0\x3E" },
- { "\x3E" , "\xF0\x3E" },
- },
-
- { // BX_KEY_9 ( ibm 10 )
- { "\x0A" , "\x8A" },
- { "\x46" , "\xF0\x46" },
- { "\x46" , "\xF0\x46" },
- },
-
- { // BX_KEY_ESC ( ibm 110 )
- { "\x01" , "\x81" },
- { "\x76" , "\xF0\x76" },
- { "\x08" , "\xF0\x08" },
- },
-
- { // BX_KEY_SPACE ( ibm 61 )
- { "\x39" , "\xB9" },
- { "\x29" , "\xF0\x29" },
- { "\x29" , "\xF0\x29" },
- },
-
- { // BX_KEY_SINGLE_QUOTE ( ibm 41 )
- { "\x28" , "\xA8" },
- { "\x52" , "\xF0\x52" },
- { "\x52" , "\xF0\x52" },
- },
-
- { // BX_KEY_COMMA ( ibm 53 )
- { "\x33" , "\xB3" },
- { "\x41" , "\xF0\x41" },
- { "\x41" , "\xF0\x41" },
- },
-
- { // BX_KEY_PERIOD ( ibm 54 )
- { "\x34" , "\xB4" },
- { "\x49" , "\xF0\x49" },
- { "\x49" , "\xF0\x49" },
- },
-
- { // BX_KEY_SLASH ( ibm 55 )
- { "\x35" , "\xB5" },
- { "\x4A" , "\xF0\x4A" },
- { "\x4A" , "\xF0\x4A" },
- },
-
- { // BX_KEY_SEMICOLON ( ibm 40 )
- { "\x27" , "\xA7" },
- { "\x4C" , "\xF0\x4C" },
- { "\x4C" , "\xF0\x4C" },
- },
-
- { // BX_KEY_EQUALS ( ibm 13 )
- { "\x0D" , "\x8D" },
- { "\x55" , "\xF0\x55" },
- { "\x55" , "\xF0\x55" },
- },
-
- { // BX_KEY_LEFT_BRACKET ( ibm 27 )
- { "\x1A" , "\x9A" },
- { "\x54" , "\xF0\x54" },
- { "\x54" , "\xF0\x54" },
- },
-
- { // BX_KEY_BACKSLASH ( ibm 42, 29)
- { "\x2B" , "\xAB" },
- { "\x5D" , "\xF0\x5D" },
- { "\x53" , "\xF0\x53" },
- },
-
- { // BX_KEY_RIGHT_BRACKET ( ibm 28 )
- { "\x1B" , "\x9B" },
- { "\x5B" , "\xF0\x5B" },
- { "\x5B" , "\xF0\x5B" },
- },
-
- { // BX_KEY_MINUS ( ibm 12 )
- { "\x0C" , "\x8C" },
- { "\x4E" , "\xF0\x4E" },
- { "\x4E" , "\xF0\x4E" },
- },
-
- { // BX_KEY_GRAVE ( ibm 1 )
- { "\x29" , "\xA9" },
- { "\x0E" , "\xF0\x0E" },
- { "\x0E" , "\xF0\x0E" },
- },
-
- { // BX_KEY_BACKSPACE ( ibm 15 )
- { "\x0E" , "\x8E" },
- { "\x66" , "\xF0\x66" },
- { "\x66" , "\xF0\x66" },
- },
-
- { // BX_KEY_ENTER ( ibm 43 )
- { "\x1C" , "\x9C" },
- { "\x5A" , "\xF0\x5A" },
- { "\x5A" , "\xF0\x5A" },
- },
-
- { // BX_KEY_TAB ( ibm 16 )
- { "\x0F" , "\x8F" },
- { "\x0D" , "\xF0\x0D" },
- { "\x0D" , "\xF0\x0D" },
- },
-
- { // BX_KEY_LEFT_BACKSLASH ( ibm 45 )
- { "\x56" , "\xD6" },
- { "\x61" , "\xF0\x61" },
- { "\x13" , "\xF0\x13" },
- },
-
- { // BX_KEY_PRINT ( ibm 124 )
- { "\xE0\x37" , "\xE0\xB7" },
- { "\xE0\x7C" , "\xE0\xF0\x7C" },
- { "\x57" , "\xF0\x57" },
- },
-
- { // BX_KEY_SCRL_LOCK ( ibm 125 )
- { "\x46" , "\xC6" },
- { "\x7E" , "\xF0\x7E" },
- { "\x5F" , "\xF0\x5F" },
- },
-
- { // BX_KEY_PAUSE ( ibm 126 )
- { "\xE1\x1D\x45\xE1\x9D\xC5" , "" },
- { "\xE1\x14\x77\xE1\xF0\x14\xF0\x77" , "" },
- { "\x62" , "\xF0\x62" },
- },
-
- { // BX_KEY_INSERT ( ibm 75 )
- { "\xE0\x52" , "\xE0\xD2" },
- { "\xE0\x70" , "\xE0\xF0\x70" },
- { "\x67" , "\xF0\x67" },
- },
-
- { // BX_KEY_DELETE ( ibm 76 )
- { "\xE0\x53" , "\xE0\xD3" },
- { "\xE0\x71" , "\xE0\xF0\x71" },
- { "\x64" , "\xF0\x64" },
- },
-
- { // BX_KEY_HOME ( ibm 80 )
- { "\xE0\x47" , "\xE0\xC7" },
- { "\xE0\x6C" , "\xE0\xF0\x6C" },
- { "\x6E" , "\xF0\x6E" },
- },
-
- { // BX_KEY_END ( ibm 81 )
- { "\xE0\x4F" , "\xE0\xCF" },
- { "\xE0\x69" , "\xE0\xF0\x69" },
- { "\x65" , "\xF0\x65" },
- },
-
- { // BX_KEY_PAGE_UP ( ibm 85 )
- { "\xE0\x49" , "\xE0\xC9" },
- { "\xE0\x7D" , "\xE0\xF0\x7D" },
- { "\x6F" , "\xF0\x6F" },
- },
-
- { // BX_KEY_PAGE_DOWN ( ibm 86 )
- { "\xE0\x51" , "\xE0\xD1" },
- { "\xE0\x7A" , "\xE0\xF0\x7A" },
- { "\x6D" , "\xF0\x6D" },
- },
-
- { // BX_KEY_KP_ADD ( ibm 106 )
- { "\x4E" , "\xCE" },
- { "\x79" , "\xF0\x79" },
- { "\x7C" , "\xF0\x7C" },
- },
-
- { // BX_KEY_KP_SUBTRACT ( ibm 105 )
- { "\x4A" , "\xCA" },
- { "\x7B" , "\xF0\x7B" },
- { "\x84" , "\xF0\x84" },
- },
-
- { // BX_KEY_KP_END ( ibm 93 )
- { "\x4F" , "\xCF" },
- { "\x69" , "\xF0\x69" },
- { "\x69" , "\xF0\x69" },
- },
-
- { // BX_KEY_KP_DOWN ( ibm 98 )
- { "\x50" , "\xD0" },
- { "\x72" , "\xF0\x72" },
- { "\x72" , "\xF0\x72" },
- },
-
- { // BX_KEY_KP_PAGE_DOWN ( ibm 103 )
- { "\x51" , "\xD1" },
- { "\x7A" , "\xF0\x7A" },
- { "\x7A" , "\xF0\x7A" },
- },
-
- { // BX_KEY_KP_LEFT ( ibm 92 )
- { "\x4B" , "\xCB" },
- { "\x6B" , "\xF0\x6B" },
- { "\x6B" , "\xF0\x6B" },
- },
-
- { // BX_KEY_KP_RIGHT ( ibm 102 )
- { "\x4D" , "\xCD" },
- { "\x74" , "\xF0\x74" },
- { "\x74" , "\xF0\x74" },
- },
-
- { // BX_KEY_KP_HOME ( ibm 91 )
- { "\x47" , "\xC7" },
- { "\x6C" , "\xF0\x6C" },
- { "\x6C" , "\xF0\x6C" },
- },
-
- { // BX_KEY_KP_UP ( ibm 96 )
- { "\x48" , "\xC8" },
- { "\x75" , "\xF0\x75" },
- { "\x75" , "\xF0\x75" },
- },
-
- { // BX_KEY_KP_PAGE_UP ( ibm 101 )
- { "\x49" , "\xC9" },
- { "\x7D" , "\xF0\x7D" },
- { "\x7D" , "\xF0\x7D" },
- },
-
- { // BX_KEY_KP_INSERT ( ibm 99 )
- { "\x52" , "\xD2" },
- { "\x70" , "\xF0\x70" },
- { "\x70" , "\xF0\x70" },
- },
-
- { // BX_KEY_KP_DELETE ( ibm 104 )
- { "\x53" , "\xD3" },
- { "\x71" , "\xF0\x71" },
- { "\x71" , "\xF0\x71" },
- },
-
- { // BX_KEY_KP_5 ( ibm 97 )
- { "\x4C" , "\xCC" },
- { "\x73" , "\xF0\x73" },
- { "\x73" , "\xF0\x73" },
- },
-
- { // BX_KEY_UP ( ibm 83 )
- { "\xE0\x48" , "\xE0\xC8" },
- { "\xE0\x75" , "\xE0\xF0\x75" },
- { "\x63" , "\xF0\x63" },
- },
-
- { // BX_KEY_DOWN ( ibm 84 )
- { "\xE0\x50" , "\xE0\xD0" },
- { "\xE0\x72" , "\xE0\xF0\x72" },
- { "\x60" , "\xF0\x60" },
- },
-
- { // BX_KEY_LEFT ( ibm 79 )
- { "\xE0\x4B" , "\xE0\xCB" },
- { "\xE0\x6B" , "\xE0\xF0\x6B" },
- { "\x61" , "\xF0\x61" },
- },
-
- { // BX_KEY_RIGHT ( ibm 89 )
- { "\xE0\x4D" , "\xE0\xCD" },
- { "\xE0\x74" , "\xE0\xF0\x74" },
- { "\x6A" , "\xF0\x6A" },
- },
-
- { // BX_KEY_KP_ENTER ( ibm 108 )
- { "\xE0\x1C" , "\xE0\x9C" },
- { "\xE0\x5A" , "\xE0\xF0\x5A" },
- { "\x79" , "\xF0\x79" },
- },
-
- { // BX_KEY_KP_MULTIPLY ( ibm 100 )
- { "\x37" , "\xB7" },
- { "\x7C" , "\xF0\x7C" },
- { "\x7E" , "\xF0\x7E" },
- },
-
- { // BX_KEY_KP_DIVIDE ( ibm 95 )
- { "\xE0\x35" , "\xE0\xB5" },
- { "\xE0\x4A" , "\xE0\xF0\x4A" },
- { "\x77" , "\xF0\x77" },
- },
-
- { // BX_KEY_WIN_L
- { "\xE0\x5B" , "\xE0\xDB" },
- { "\xE0\x1F" , "\xE0\xF0\x1F" },
- { "\x8B" , "\xF0\x8B" },
- },
-
- { // BX_KEY_WIN_R
- { "\xE0\x5C" , "\xE0\xDC" },
- { "\xE0\x27" , "\xE0\xF0\x27" },
- { "\x8C" , "\xF0\x8C" },
- },
-
- { // BX_KEY_MENU
- { "\xE0\x5D" , "\xE0\xDD" },
- { "\xE0\x2F" , "\xE0\xF0\x2F" },
- { "\x8D" , "\xF0\x8D" },
- },
-
- { // BX_KEY_ALT_SYSREQ
- { "\x54" , "\xD4" },
- { "\x84" , "\xF0\x84" },
- { "\x57" , "\xF0\x57" },
- },
-
- { // BX_KEY_CTRL_BREAK
- { "\xE0\x46" , "\xE0\xC6" },
- { "\xE0\x7E" , "\xE0\xF0\x7E" },
- { "\x62" , "\xF0\x62" },
- },
-
- { // BX_KEY_INT_BACK
- { "\xE0\x6A" , "\xE0\xEA" },
- { "\xE0\x38" , "\xE0\xF0\x38" },
- { "\x38" , "\xF0\x38" },
- },
-
- { // BX_KEY_INT_FORWARD
- { "\xE0\x69" , "\xE0\xE9" },
- { "\xE0\x30" , "\xE0\xF0\x30" },
- { "\x30" , "\xF0\x30" },
- },
-
- { // BX_KEY_INT_STOP
- { "\xE0\x68" , "\xE0\xE8" },
- { "\xE0\x28" , "\xE0\xF0\x28" },
- { "\x28" , "\xF0\x28" },
- },
-
- { // BX_KEY_INT_MAIL
- { "\xE0\x6C" , "\xE0\xEC" },
- { "\xE0\x48" , "\xE0\xF0\x48" },
- { "\x48" , "\xF0\x48" },
- },
-
- { // BX_KEY_INT_SEARCH
- { "\xE0\x65" , "\xE0\xE5" },
- { "\xE0\x10" , "\xE0\xF0\x10" },
- { "\x10" , "\xF0\x10" },
- },
-
- { // BX_KEY_INT_FAV
- { "\xE0\x66" , "\xE0\xE6" },
- { "\xE0\x18" , "\xE0\xF0\x18" },
- { "\x18" , "\xF0\x18" },
- },
-
- { // BX_KEY_INT_HOME
- { "\xE0\x32" , "\xE0\xB2" },
- { "\xE0\x3A" , "\xE0\xF0\x3A" },
- { "\x97" , "\xF0\x97" },
- },
-
- { // BX_KEY_POWER_MYCOMP
- { "\xE0\x6B" , "\xE0\xEB" },
- { "\xE0\x40" , "\xE0\xF0\x40" },
- { "\x40" , "\xF0\x40" },
- },
-
- { // BX_KEY_POWER_CALC
- { "\xE0\x21" , "\xE0\xA1" },
- { "\xE0\x2B" , "\xE0\xF0\x2B" },
- { "\x99" , "\xF0\x99" },
- },
-
- { // BX_KEY_POWER_SLEEP
- { "\xE0\x5F" , "\xE0\xDF" },
- { "\xE0\x3F" , "\xE0\xF0\x3F" },
- { "\x7F" , "\xF0\x7F" },
- },
-
- { // BX_KEY_POWER_POWER
- { "\xE0\x5E" , "\xE0\xDE" },
- { "\xE0\x37" , "\xE0\xF0\x37" },
- { "" , "" },
- },
-
- { // BX_KEY_POWER_WAKE
- { "\xE0\x63" , "\xE0\xE3" },
- { "\xE0\x5E" , "\xE0\xF0\x5E" },
- { "" , "" },
- },
-
-};
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: scancodes.h,v 1.4 2002/10/24 21:07:51 bdenney Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-// Translation table of the 8042
-extern unsigned char translation8042[256];
-
-typedef struct {
- const char *make;
- const char *brek;
- }scancode;
-
-// Scancodes table
-extern scancode scancodes[BX_KEY_NBKEYS][3];
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: scsi_commands.h,v 1.3 2001/10/03 13:10:38 bdenney Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-/* scsi/commands.h
- Used only in cdrom_amigaos.cc.
-
- Operation codes for SCSI-2 commands
-
- 30 Nov 94 Peter Urbanec Created file
- 10 Jan 95 Peter Urbanec Added SCSI_ prefix to all commands
- 31 Jan 95 Peter Urbanec Released to public
-
-*/
-
-
-/* All device types */
-
-#define SCSI_CHANGE_DEFINITION 0x40
-#define SCSI_COMPARE 0x39
-#define SCSI_COPY 0x18
-#define SCSI_COPY_AND_VERIFY 0x3a
-#define SCSI_INQUIRY 0x12
-#define SCSI_LOG_SELECT 0x4c
-#define SCSI_LOG_SENSE 0x4d
-#define SCSI_MODE_SELECT_6 0x15
-#define SCSI_MODE_SELECT_10 0x55
-#define SCSI_MODE_SENSE_6 0x1a
-#define SCSI_MODE_SENSE_10 0x5a
-#define SCSI_READ_BUFFER 0x3c
-#define SCSI_RECEIVE_DIAGNOSTIC_RESULTS 0x1c
-#define SCSI_REQUEST_SENSE 0x03
-#define SCSI_SEND_DIAGNOSTIC 0x1d
-#define SCSI_TEST_UNIT_READY 0x00
-#define SCSI_WRITE_BUFFER 0x3b
-
-
-/* Direct Access devices */
-
-#define SCSI_DA_CHANGE_DEFINITION 0x40
-#define SCSI_DA_COMPARE 0x39
-#define SCSI_DA_COPY 0x18
-#define SCSI_DA_COPY_AND_VERIFY 0x3a
-#define SCSI_DA_FORMAT_UNIT 0x04
-#define SCSI_DA_INQUIRY 0x12
-#define SCSI_DA_LOCK_UNLOCK_CACHE 0x36
-#define SCSI_DA_LOG_SELECT 0x4c
-#define SCSI_DA_LOG_SENSE 0x4d
-#define SCSI_DA_MODE_SELECT_6 0x15
-#define SCSI_DA_MODE_SELECT_10 0x55
-#define SCSI_DA_MODE_SENSE_6 0x1a
-#define SCSI_DA_MODE_SENSE_10 0x5a
-#define SCSI_DA_PRE_FETCH 0x34
-#define SCSI_DA_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e
-#define SCSI_DA_READ_6 0x08
-#define SCSI_DA_READ_10 0x28
-#define SCSI_DA_READ_BUFFER 0x3c
-#define SCSI_DA_READ_CAPACITY 0x25
-#define SCSI_DA_READ_DEFECT_DATA 0x37
-#define SCSI_DA_READ_LONG 0x3e
-#define SCSI_DA_REASSIGN_BLOCKS 0x07
-#define SCSI_DA_RECEIVE_DIAGNOSTIC_RESULTS 0x1c
-#define SCSI_DA_RELEASE 0x17
-#define SCSI_DA_REQUEST_SENSE 0x03
-#define SCSI_DA_RESERVE 0x16
-#define SCSI_DA_REZERO_UNIT 0x01
-#define SCSI_DA_SEARCH_DATA_EQUAL 0x31
-#define SCSI_DA_SEARCH_DATA_HIGH 0x30
-#define SCSI_DA_SEARCH_DATA_LOW 0x32
-#define SCSI_DA_SEEK_6 0x0b
-#define SCSI_DA_SEEK_10 0x2b
-#define SCSI_DA_SEND_DIAGNOSTIC 0x1d
-#define SCSI_DA_SET_LIMITS 0x33
-#define SCSI_DA_START_STOP_UNIT 0x1b
-#define SCSI_DA_SYNCHRONIZE_CACHE 0x35
-#define SCSI_DA_TEST_UNIT_READY 0x00
-#define SCSI_DA_VERIFY 0x2f
-
-
-/* Sequential access devices */
-
-#define SCSI_SA_CHANGE_DEFINITION 0x40
-#define SCSI_SA_COMPARE 0x39
-#define SCSI_SA_COPY 0x18
-#define SCSI_SA_COPY_AND_VERIFY 0x3a
-#define SCSI_SA_ERASE 0x19
-#define SCSI_SA_INQUIRY 0x12
-#define SCSI_SA_LOAD_UNLOAD 0x1b
-#define SCSI_SA_LOCATE 0x2b
-#define SCSI_SA_LOG_SELECT 0x4c
-#define SCSI_SA_LOG_SENSE 0x4d
-#define SCSI_SA_MODE_SELECT_6 0x15
-#define SCSI_SA_MODE_SELECT_10 0x55
-#define SCSI_SA_MODE_SENSE_6 0x1a
-#define SCSI_SA_MODE_SENSE_10 0x5a
-#define SCSI_SA_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e
-#define SCSI_SA_READ 0x08
-#define SCSI_SA_READ_BLOCK_LIMITS 0x05
-#define SCSI_SA_READ_BUFFER 0x3c
-#define SCSI_SA_READ_POSITION 0x34
-#define SCSI_SA_READ_REVERSE 0x0f
-#define SCSI_SA_RECEIVE_DIAGNOSTIC_RESULTS 0x1c
-#define SCSI_SA_RECOVER_BUFFERED_DATA 0x14
-#define SCSI_SA_RELEASE_UNIT 0x17
-#define SCSI_SA_REQUEST_SENSE 0x03
-#define SCSI_SA_RESERVE_UNIT 0x16
-#define SCSI_SA_REWIND 0x01
-#define SCSI_SA_SEND_DIAGNOSTIC 0x1d
-#define SCSI_SA_SPACE 0x11
-#define SCSI_SA_TEST_UNIT_READY 0x00
-#define SCSI_SA_VERIFY 0x13
-#define SCSI_SA_WRITE 0x0a
-#define SCSI_SA_WRITE_BUFFER 0x3b
-#define SCSI_SA_WRITE_FILEMARKS 0x10
-
-
-/* Printer devices */
-
-#define SCSI_PRT_CHANGE_DEFINITION 0x40
-#define SCSI_PRT_COMPARE 0x39
-#define SCSI_PRT_COPY 0x18
-#define SCSI_PRT_COPY_AND_VERIFY 0x3a
-#define SCSI_PRT_FORMAT 0x04
-#define SCSI_PRT_INQUIRY 0x12
-#define SCSI_PRT_LOG_SELECT 0x4c
-#define SCSI_PRT_LOG_SENSE 0x4d
-#define SCSI_PRT_MODE_SELECT_6 0x15
-#define SCSI_PRT_MODE_SELECT_10 0x55
-#define SCSI_PRT_MODE_SENSE_6 0x1a
-#define SCSI_PRT_MODE_SENSE_10 0x5a
-#define SCSI_PRT_PRINT 0x0a
-#define SCSI_PRT_READ_BUFFER 0x3c
-#define SCSI_PRT_RECEIVE_DIAGNOSTIC_RESULTS 0x1c
-#define SCSI_PRT_RECOVER_BUFFERED_DATA 0x14
-#define SCSI_PRT_RELEASE_UNIT 0x17
-#define SCSI_PRT_REQUEST_SENSE 0x03
-#define SCSI_PRT_RESERVE_UNIT 0x16
-#define SCSI_PRT_SEND_DIAGNOSTIC 0x1d
-#define SCSI_PRT_SLEW_AND_PRINT 0x0b
-#define SCSI_PRT_STOP_PRINT 0x1b
-#define SCSI_PRT_SYNCHRONIZE_BUFFER 0x10
-#define SCSI_PRT_TEST_UNIT_READY 0x00
-#define SCSI_PRT_WRITE_BUFFER 0x3b
-
-
-/* Processor devices */
-
-#define SCSI_CPU_CHANGE_DEFINITION 0x40
-#define SCSI_CPU_COMPARE 0x39
-#define SCSI_CPU_COPY 0x18
-#define SCSI_CPU_COPY_AND_VERIFY 0x3a
-#define SCSI_CPU_INQUIRY 0x12
-#define SCSI_CPU_LOG_SELECT 0x4c
-#define SCSI_CPU_LOG_SENSE 0x4d
-#define SCSI_CPU_READ_BUFFER 0x3c
-#define SCSI_CPU_RECEIVE 0x08
-#define SCSI_CPU_RECEIVE_DIAGNOSTIC_RESULTS 0x1c
-#define SCSI_CPU_REQUEST_SENSE 0x03
-#define SCSI_CPU_SEND 0x0a
-#define SCSI_CPU_SEND_DIAGNOSTIC 0x1d
-#define SCSI_CPU_TEST_UNIT_READY 0x00
-#define SCSI_CPU_WRITE_BUFFER 0x3b
-
-
-/* Write Once devices */
-
-#define SCSI_WO_CHANGE_DEFINITION 0x40
-#define SCSI_WO_COMPARE 0x39
-#define SCSI_WO_COPY 0x18
-#define SCSI_WO_COPY_AND_VERIFY 0x3a
-#define SCSI_WO_INQUIRY 0x12
-#define SCSI_WO_LOCK_UNLOCK_CACHE 0x36
-#define SCSI_WO_LOG_SELECT 0x4c
-#define SCSI_WO_LOG_SENSE 0x4d
-#define SCSI_WO_MEDIUM_SCAN 0x38
-#define SCSI_WO_MODE_SELECT_6 0x15
-#define SCSI_WO_MODE_SELECT_10 0x55
-#define SCSI_WO_MODE_SENSE_6 0x1a
-#define SCSI_WO_MODE_SENSE_10 0x5a
-#define SCSI_WO_PRE_FETCH 0x34
-#define SCSI_WO_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e
-#define SCSI_WO_READ_6 0x08
-#define SCSI_WO_READ_10 0x28
-#define SCSI_WO_READ_12 0xa8
-#define SCSI_WO_READ_BUFFER 0x3c
-#define SCSI_WO_READ_CAPACITY 0x25
-#define SCSI_WO_READ_LONG 0x3e
-#define SCSI_WO_REASSIGN_BLOCKS 0x07
-#define SCSI_WO_RECEIVE_DIAGNOSTIC_RESULTS 0x1c
-#define SCSI_WO_RELEASE 0x17
-#define SCSI_WO_REQUEST_SENSE 0x03
-#define SCSI_WO_RESERVE 0x16
-#define SCSI_WO_REZERO_UNIT 0x01
-#define SCSI_WO_SEARCH_DATA_EQUAL_10 0x31
-#define SCSI_WO_SEARCH_DATA_EQUAL_12 0xb1
-#define SCSI_WO_SEARCH_DATA_HIGH_10 0x30
-#define SCSI_WO_SEARCH_DATA_HIGH_12 0xb0
-#define SCSI_WO_SEARCH_DATA_LOW_10 0x32
-#define SCSI_WO_SEARCH_DATA_LOW_12 0xb2
-#define SCSI_WO_SEEK_6 0x0b
-#define SCSI_WO_SEEK_10 0x2b
-#define SCSI_WO_SEND_DIAGNOSTIC 0x1d
-#define SCSI_WO_SET_LIMITS_10 0x33
-#define SCSI_WO_SET_LIMITS_12 0xb3
-#define SCSI_WO_START_STOP_UNIT 0x1b
-#define SCSI_WO_SYNCHRONIZE_CACHE 0x35
-#define SCSI_WO_TEST_UNIT_READY 0x00
-#define SCSI_WO_VERIFY_10 0x2f
-#define SCSI_WO_VERIFY_12 0xaf
-#define SCSI_WO_WRITE_6 0x0a
-#define SCSI_WO_WRITE_10 0x2a
-#define SCSI_WO_WRITE_12 0xaa
-#define SCSI_WO_WRITE_AND_VERIFY_10 0x2e
-#define SCSI_WO_WRITE_AND_VERIFY_12 0xae
-#define SCSI_WO_WRITE_BUFFER 0x3b
-#define SCSI_WO_WRITE_LONG 0x3f
-
-
-/* CD-ROM devices */
-
-#define SCSI_CD_CHANGE_DEFINITION 0x40
-#define SCSI_CD_COMPARE 0x39
-#define SCSI_CD_COPY 0x18
-#define SCSI_CD_COPY_AND_VERIFY 0x3a
-#define SCSI_CD_INQUIRY 0x12
-#define SCSI_CD_LOCK_UNLOCK_CACHE 0x36
-#define SCSI_CD_LOG_SELECT 0x4c
-#define SCSI_CD_LOG_SENSE 0x4d
-#define SCSI_CD_MODE_SELECT_6 0x15
-#define SCSI_CD_MODE_SELECT_10 0x55
-#define SCSI_CD_MODE_SENSE_6 0x1a
-#define SCSI_CD_MODE_SENSE_10 0x5a
-#define SCSI_CD_PAUSE_RESUME 0x4b
-#define SCSI_CD_PLAY_AUDIO_10 0x45
-#define SCSI_CD_PLAY_AUDIO_12 0xa5
-#define SCSI_CD_PLAY_AUDIO_MSF 0x47
-#define SCSI_CD_PLAY_AUDIO_TRACK_INDEX 0x48
-#define SCSI_CD_PLAY_TRACK_RELATIVE_10 0x49
-#define SCSI_CD_PLAY_TRACK_RELATIVE_12 0xa9
-#define SCSI_CD_PRE_FETCH 0x34
-#define SCSI_CD_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e
-#define SCSI_CD_READ_6 0x08
-#define SCSI_CD_READ_10 0x28
-#define SCSI_CD_READ_12 0xa8
-#define SCSI_CD_READ_BUFFER 0x3c
-#define SCSI_CD_READ_CD_ROM_CAPACITY 0x25
-#define SCSI_CD_READ_HEADER 0x44
-#define SCSI_CD_READ_LONG 0x3e
-#define SCSI_CD_READ_SUB_CHANNEL 0x42
-#define SCSI_CD_READ_TOC 0x43
-#define SCSI_CD_RECEIVE_DIAGNOSTIC_RESULT 0x1c
-#define SCSI_CD_RELEASE 0x17
-#define SCSI_CD_REQUEST_SENSE 0x03
-#define SCSI_CD_RESERVE 0x16
-#define SCSI_CD_REZERO_UNIT 0x01
-#define SCSI_CD_SEARCH_DATA_EQUAL_10 0x31
-#define SCSI_CD_SEARCH_DATA_EQUAL_12 0xb1
-#define SCSI_CD_SEARCH_DATA_HIGH_10 0x30
-#define SCSI_CD_SEARCH_DATA_HIGH_12 0xb0
-#define SCSI_CD_SEARCH_DATA_LOW_10 0x32
-#define SCSI_CD_SEARCH_DATA_LOW_12 0xb2
-#define SCSI_CD_SEEK_6 0x0b
-#define SCSI_CD_SEEK_10 0x2b
-#define SCSI_CD_SEND_DIAGNOSTIC 0x1d
-#define SCSI_CD_SET_LIMITS_10 0x33
-#define SCSI_CD_SET_LIMITS_12 0xb3
-#define SCSI_CD_START_STOP_UNIT 0x1b
-#define SCSI_CD_SYNCHRONIZE_CACHE 0x35
-#define SCSI_CD_TEST_UNIT_READY 0x00
-#define SCSI_CD_VERIFY_10 0x2f
-#define SCSI_CD_VERIFY_12 0xaf
-#define SCSI_CD_WRITE_BUFFER 0x3b
-
-
-/* Scanner devices */
-
-#define SCSI_SC_CHANGE_DEFINITION 0x40
-#define SCSI_SC_COMPARE 0x39
-#define SCSI_SC_COPY 0x18
-#define SCSI_SC_COPY_AND_VERIFY 0x3a
-#define SCSI_SC_GET_DATA_BUFFER_STATUS 0x34
-#define SCSI_SC_GET_WINDOW 0x25
-#define SCSI_SC_INQUIRY 0x12
-#define SCSI_SC_LOG_SELECT 0x4c
-#define SCSI_SC_LOG_SENSE 0x4d
-#define SCSI_SC_MODE_SELECT_6 0x15
-#define SCSI_SC_MODE_SELECT_10 0x55
-#define SCSI_SC_MODE_SENSE_6 0x1a
-#define SCSI_SC_MODE_SENSE_10 0x5a
-#define SCSI_SC_OBJECT_POSITION 0x31
-#define SCSI_SC_READ 0x28
-#define SCSI_SC_READ_BUFFER 0x3c
-#define SCSI_SC_RECEIVE_DIAGNOSTIC_RESULTS 0x1c
-#define SCSI_SC_RELEASE_UNIT 0x17
-#define SCSI_SC_REQUEST_SENSE 0x03
-#define SCSI_SC_RESERVE_UNIT 0x16
-#define SCSI_SC_SCAN 0x1b
-#define SCSI_SC_SET_WINDOW 0x24
-#define SCSI_SC_SEND 0x2a
-#define SCSI_SC_SEND_DIAGNOSTIC 0x1d
-#define SCSI_SC_TEST_UNIT_READY 0x00
-#define SCSI_SC_WRITE_BUFFER 0x3b
-
-
-/* Optical memory devices */
-
-#define SCSI_OM_CHANGE_DEFINITION 0x40
-#define SCSI_OM_COMPARE 0x39
-#define SCSI_OM_COPY 0x18
-#define SCSI_OM_COPY_AND_VERIFY 0x3a
-#define SCSI_OM_ERASE_10 0x2c
-#define SCSI_OM_ERASE_12 0xac
-#define SCSI_OM_FORMAT_UNIT 0x04
-#define SCSI_OM_INQUIRY 0x12
-#define SCSI_OM_LOCK_UNLOCK_CACHE 0x36
-#define SCSI_OM_LOG_SELECT 0x4c
-#define SCSI_OM_LOG_SENSE 0x4d
-#define SCSI_OM_MEDIUM_SCAN 0x38
-#define SCSI_OM_MODE_SELECT_6 0x15
-#define SCSI_OM_MODE_SELECT_10 0x55
-#define SCSI_OM_MODE_SENSE_6 0x1a
-#define SCSI_OM_MODE_SENSE_10 0x5a
-#define SCSI_OM_PRE_FETCH 0x34
-#define SCSI_OM_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e
-#define SCSI_OM_READ_6 0x08
-#define SCSI_OM_READ_10 0x28
-#define SCSI_OM_READ_12 0xa8
-#define SCSI_OM_READ_BUFFER 0x3c
-#define SCSI_OM_READ_CAPACITY 0x25
-#define SCSI_OM_READ_DEFECT_DATA_10 0x37
-#define SCSI_OM_READ_DEFECT_DATA_12 0xb7
-#define SCSI_OM_READ_GENERATION 0x29
-#define SCSI_OM_READ_LONG 0x3e
-#define SCSI_OM_READ_UPDATED_BLOCK 0x2d
-#define SCSI_OM_REASSIGN_BLOCKS 0x07
-#define SCSI_OM_RECEIVE_DIAGNOSTIC_RESULTS 0x1c
-#define SCSI_OM_RELEASE 0x17
-#define SCSI_OM_REQUEST_SENSE 0x03
-#define SCSI_OM_RESERVE 0x16
-#define SCSI_OM_REZERO_UNIT 0x01
-#define SCSI_OM_SEARCH_DATA_EQUAL_10 0x31
-#define SCSI_OM_SEARCH_DATA_EQUAL_12 0xb1
-#define SCSI_OM_SEARCH_DATA_HIGH_10 0x30
-#define SCSI_OM_SEARCH_DATA_HIGH_12 0xb0
-#define SCSI_OM_SEARCH_DATA_LOW_10 0x32
-#define SCSI_OM_SEARCH_DATA_LOW_12 0xb2
-#define SCSI_OM_SEEK_6 0x0b
-#define SCSI_OM_SEEK_10 0x2b
-#define SCSI_OM_SEND_DIAGNOSTIC 0x1d
-#define SCSI_OM_SET_LIMITS_10 0x33
-#define SCSI_OM_SET_LIMITS_12 0xb3
-#define SCSI_OM_START_STOP_UNIT 0x1b
-#define SCSI_OM_SYNCHRONIZE_CACHE 0x35
-#define SCSI_OM_TEST_UNIT_READY 0x00
-#define SCSI_OM_UPDATE_BLOCK 0x3d
-#define SCSI_OM_VERIFY_10 0x2f
-#define SCSI_OM_VERIFY_12 0xaf
-#define SCSI_OM_WRITE_6 0x0a
-#define SCSI_OM_WRITE_10 0x2a
-#define SCSI_OM_WRITE_12 0xaa
-#define SCSI_OM_WRITE_AND_VERIFY_10 0x2e
-#define SCSI_OM_WRITE_AND_VERIFY_12 0xae
-#define SCSI_OM_WRITE_BUFFER 0x3b
-#define SCSI_OM_WRITE_LONG 0x3f
-
-
-/* Medium changer devices */
-
-#define SCSI_MC_CHANGE_DEFINITION 0x40
-#define SCSI_MC_EXCHANGE_MEDIUM 0xa6
-#define SCSI_MC_INITIALIZE_ELEMENT_STATUS 0x07
-#define SCSI_MC_INQUIRY 0x12
-#define SCSI_MC_LOG_SELECT 0x4c
-#define SCSI_MC_LOG_SENSE 0x4d
-#define SCSI_MC_MODE_SELECT_6 0x15
-#define SCSI_MC_MODE_SELECT_10 0x55
-#define SCSI_MC_MODE_SENSE_6 0x1a
-#define SCSI_MC_MODE_SENSE_10 0x5a
-#define SCSI_MC_MOVE_MEDIUM 0xa5
-#define SCSI_MC_POSITION_TO_ELEMENT 0x2b
-#define SCSI_MC_PREVENT_ALLOW_MEDIUM_REMOVAL 0x1e
-#define SCSI_MC_READ_BUFFER 0x3c
-#define SCSI_MC_READ_ELEMENT_STATUS 0xb8
-#define SCSI_MC_RECEIVE_DIAGNOSTIC_RESULTS 0x1c
-#define SCSI_MC_RELEASE 0x17
-#define SCSI_MC_REQUEST_VOLUME_ELEMENT_ADDRESS 0xb5
-#define SCSI_MC_REQUEST_SENSE 0x03
-#define SCSI_MC_RESERVE 0x16
-#define SCSI_MC_REZERO_UNIT 0x01
-#define SCSI_MC_SEND_DIAGNOSTIC 0x1d
-#define SCSI_MC_SEND_VOLUME_TAG 0xb6
-#define SCSI_MC_TEST_UNIT_READY 0x00
-#define SCSI_MC_WRITE_BUFFER 0x3b
-
-
-/* Communications devices */
-
-#define SCSI_COM_CHANGE_DEFINITION 0x40
-#define SCSI_COM_GET_MESSAGE_6 0x08
-#define SCSI_COM_GET_MESSAGE_10 0x28
-#define SCSI_COM_GET_MESSAGE_12 0xa8
-#define SCSI_COM_INQUIRY 0x12
-#define SCSI_COM_LOG_SELECT 0x4c
-#define SCSI_COM_LOG_SENSE 0x4d
-#define SCSI_COM_MODE_SELECT_6 0x15
-#define SCSI_COM_MODE_SELECT_10 0x55
-#define SCSI_COM_MODE_SENSE_6 0x1a
-#define SCSI_COM_MODE_SENSE_10 0x5a
-#define SCSI_COM_READ_BUFFER 0x3c
-#define SCSI_COM_RECEIVE_DIAGNOSTIC_RESULTS 0x1c
-#define SCSI_COM_REQUEST_SENSE 0x03
-#define SCSI_COM_SEND_DIAGNOSTIC 0x1d
-#define SCSI_COM_SEND_MESSAGE_6 0x0a
-#define SCSI_COM_SEND_MESSAGE_10 0x2a
-#define SCSI_COM_SEND_MESSAGE_12 0xaa
-#define SCSI_COM_TEST_UNIT_READY 0x00
-#define SCSI_COM_WRITE_BUFFER 0x3b
-
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: scsidefs.h,v 1.4 2002/09/16 16:58:36 bdenney Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-//
-// iodev/scsidefs.h
-// $Id: scsidefs.h,v 1.4 2002/09/16 16:58:36 bdenney Exp $
-//
-// This file was copied from ... ?
-//
-
-//***************************************************************************
-//
-// Name: SCSIDEFS.H
-//
-// Description: SCSI definitions ('C' Language)
-//
-//***************************************************************************
-
-//***************************************************************************
-// %%% TARGET STATUS VALUES %%%
-//***************************************************************************
-#define STATUS_GOOD 0x00 // Status Good
-#define STATUS_CHKCOND 0x02 // Check Condition
-#define STATUS_CONDMET 0x04 // Condition Met
-#define STATUS_BUSY 0x08 // Busy
-#define STATUS_INTERM 0x10 // Intermediate
-#define STATUS_INTCDMET 0x14 // Intermediate-condition met
-#define STATUS_RESCONF 0x18 // Reservation conflict
-#define STATUS_COMTERM 0x22 // Command Terminated
-#define STATUS_QFULL 0x28 // Queue full
-
-//***************************************************************************
-// %%% SCSI MISCELLANEOUS EQUATES %%%
-//***************************************************************************
-#define MAXLUN 7 // Maximum Logical Unit Id
-#define MAXTARG 7 // Maximum Target Id
-#define MAX_SCSI_LUNS 64 // Maximum Number of SCSI LUNs
-#define MAX_NUM_HA 8 // Maximum Number of SCSI HA's
-
-//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
-//
-// %%% SCSI COMMAND OPCODES %%%
-//
-///\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
-
-//***************************************************************************
-// %%% Commands for all Device Types %%%
-//***************************************************************************
-#define SCSI_CHANGE_DEF 0x40 // Change Definition (Optional)
-#define SCSI_COMPARE 0x39 // Compare (O)
-#define SCSI_COPY 0x18 // Copy (O)
-#define SCSI_COP_VERIFY 0x3A // Copy and Verify (O)
-#define SCSI_INQUIRY 0x12 // Inquiry (MANDATORY)
-#define SCSI_LOG_SELECT 0x4C // Log Select (O)
-#define SCSI_LOG_SENSE 0x4D // Log Sense (O)
-#define SCSI_MODE_SEL6 0x15 // Mode Select 6-byte (Device Specific)
-#define SCSI_MODE_SEL10 0x55 // Mode Select 10-byte (Device Specific)
-#define SCSI_MODE_SEN6 0x1A // Mode Sense 6-byte (Device Specific)
-#define SCSI_MODE_SEN10 0x5A // Mode Sense 10-byte (Device Specific)
-#define SCSI_READ_BUFF 0x3C // Read Buffer (O)
-#define SCSI_REQ_SENSE 0x03 // Request Sense (MANDATORY)
-#define SCSI_SEND_DIAG 0x1D // Send Diagnostic (O)
-#define SCSI_TST_U_RDY 0x00 // Test Unit Ready (MANDATORY)
-#define SCSI_WRITE_BUFF 0x3B // Write Buffer (O)
-
-//***************************************************************************
-// %%% Commands Unique to Direct Access Devices %%%
-//***************************************************************************
-#define SCSI_COMPARE 0x39 // Compare (O)
-#define SCSI_FORMAT 0x04 // Format Unit (MANDATORY)
-#define SCSI_LCK_UN_CAC 0x36 // Lock Unlock Cache (O)
-#define SCSI_PREFETCH 0x34 // Prefetch (O)
-#define SCSI_MED_REMOVL 0x1E // Prevent/Allow medium Removal (O)
-#define SCSI_READ6 0x08 // Read 6-byte (MANDATORY)
-#define SCSI_READ10 0x28 // Read 10-byte (MANDATORY)
-#define SCSI_RD_CAPAC 0x25 // Read Capacity (MANDATORY)
-#define SCSI_RD_DEFECT 0x37 // Read Defect Data (O)
-#define SCSI_READ_LONG 0x3E // Read Long (O)
-#define SCSI_REASS_BLK 0x07 // Reassign Blocks (O)
-#define SCSI_RCV_DIAG 0x1C // Receive Diagnostic Results (O)
-#define SCSI_RELEASE 0x17 // Release Unit (MANDATORY)
-#define SCSI_REZERO 0x01 // Rezero Unit (O)
-#define SCSI_SRCH_DAT_E 0x31 // Search Data Equal (O)
-#define SCSI_SRCH_DAT_H 0x30 // Search Data High (O)
-#define SCSI_SRCH_DAT_L 0x32 // Search Data Low (O)
-#define SCSI_SEEK6 0x0B // Seek 6-Byte (O)
-#define SCSI_SEEK10 0x2B // Seek 10-Byte (O)
-#define SCSI_SEND_DIAG 0x1D // Send Diagnostics (MANDATORY)
-#define SCSI_SET_LIMIT 0x33 // Set Limits (O)
-#define SCSI_START_STP 0x1B // Start/Stop Unit (O)
-#define SCSI_SYNC_CACHE 0x35 // Synchronize Cache (O)
-#define SCSI_VERIFY 0x2F // Verify (O)
-#define SCSI_WRITE6 0x0A // Write 6-Byte (MANDATORY)
-#define SCSI_WRITE10 0x2A // Write 10-Byte (MANDATORY)
-#define SCSI_WRT_VERIFY 0x2E // Write and Verify (O)
-#define SCSI_WRITE_LONG 0x3F // Write Long (O)
-#define SCSI_WRITE_SAME 0x41 // Write Same (O)
-
-//***************************************************************************
-// %%% Commands Unique to Sequential Access Devices %%%
-//***************************************************************************
-#define SCSI_ERASE 0x19 // Erase (MANDATORY)
-#define SCSI_LOAD_UN 0x1B // Load/Unload (O)
-#define SCSI_LOCATE 0x2B // Locate (O)
-#define SCSI_RD_BLK_LIM 0x05 // Read Block Limits (MANDATORY)
-#define SCSI_READ_POS 0x34 // Read Position (O)
-#define SCSI_READ_REV 0x0F // Read Reverse (O)
-#define SCSI_REC_BF_DAT 0x14 // Recover Buffer Data (O)
-#define SCSI_RESERVE 0x16 // Reserve Unit (MANDATORY)
-#define SCSI_REWIND 0x01 // Rewind (MANDATORY)
-#define SCSI_SPACE 0x11 // Space (MANDATORY)
-#define SCSI_VERIFY_T 0x13 // Verify (Tape) (O)
-#define SCSI_WRT_FILE 0x10 // Write Filemarks (MANDATORY)
-
-//***************************************************************************
-// %%% Commands Unique to Printer Devices %%%
-//***************************************************************************
-#define SCSI_PRINT 0x0A // Print (MANDATORY)
-#define SCSI_SLEW_PNT 0x0B // Slew and Print (O)
-#define SCSI_STOP_PNT 0x1B // Stop Print (O)
-#define SCSI_SYNC_BUFF 0x10 // Synchronize Buffer (O)
-
-//***************************************************************************
-// %%% Commands Unique to Processor Devices %%%
-//***************************************************************************
-#define SCSI_RECEIVE 0x08 // Receive (O)
-#define SCSI_SEND 0x0A // Send (O)
-
-//***************************************************************************
-// %%% Commands Unique to Write-Once Devices %%%
-//***************************************************************************
-#define SCSI_MEDIUM_SCN 0x38 // Medium Scan (O)
-#define SCSI_SRCHDATE10 0x31 // Search Data Equal 10-Byte (O)
-#define SCSI_SRCHDATE12 0xB1 // Search Data Equal 12-Byte (O)
-#define SCSI_SRCHDATH10 0x30 // Search Data High 10-Byte (O)
-#define SCSI_SRCHDATH12 0xB0 // Search Data High 12-Byte (O)
-#define SCSI_SRCHDATL10 0x32 // Search Data Low 10-Byte (O)
-#define SCSI_SRCHDATL12 0xB2 // Search Data Low 12-Byte (O)
-#define SCSI_SET_LIM_10 0x33 // Set Limits 10-Byte (O)
-#define SCSI_SET_LIM_12 0xB3 // Set Limits 10-Byte (O)
-#define SCSI_VERIFY10 0x2F // Verify 10-Byte (O)
-#define SCSI_VERIFY12 0xAF // Verify 12-Byte (O)
-#define SCSI_WRITE12 0xAA // Write 12-Byte (O)
-#define SCSI_WRT_VER10 0x2E // Write and Verify 10-Byte (O)
-#define SCSI_WRT_VER12 0xAE // Write and Verify 12-Byte (O)
-
-//***************************************************************************
-// %%% Commands Unique to CD-ROM Devices %%%
-//***************************************************************************
-#define SCSI_PLAYAUD_10 0x45 // Play Audio 10-Byte (O)
-#define SCSI_PLAYAUD_12 0xA5 // Play Audio 12-Byte 12-Byte (O)
-#define SCSI_PLAYAUDMSF 0x47 // Play Audio MSF (O)
-#define SCSI_PLAYA_TKIN 0x48 // Play Audio Track/Index (O)
-#define SCSI_PLYTKREL10 0x49 // Play Track Relative 10-Byte (O)
-#define SCSI_PLYTKREL12 0xA9 // Play Track Relative 12-Byte (O)
-#define SCSI_READCDCAP 0x25 // Read CD-ROM Capacity (MANDATORY)
-#define SCSI_READHEADER 0x44 // Read Header (O)
-#define SCSI_SUBCHANNEL 0x42 // Read Subchannel (O)
-#define SCSI_READ_TOC 0x43 // Read TOC (O)
-
-//***************************************************************************
-// %%% Commands Unique to Scanner Devices %%%
-//***************************************************************************
-#define SCSI_GETDBSTAT 0x34 // Get Data Buffer Status (O)
-#define SCSI_GETWINDOW 0x25 // Get Window (O)
-#define SCSI_OBJECTPOS 0x31 // Object Postion (O)
-#define SCSI_SCAN 0x1B // Scan (O)
-#define SCSI_SETWINDOW 0x24 // Set Window (MANDATORY)
-
-//***************************************************************************
-// %%% Commands Unique to Optical Memory Devices %%%
-//***************************************************************************
-#define SCSI_UpdateBlk 0x3D // Update Block (O)
-
-//***************************************************************************
-// %%% Commands Unique to Medium Changer Devices %%%
-//***************************************************************************
-#define SCSI_EXCHMEDIUM 0xA6 // Exchange Medium (O)
-#define SCSI_INITELSTAT 0x07 // Initialize Element Status (O)
-#define SCSI_POSTOELEM 0x2B // Position to Element (O)
-#define SCSI_REQ_VE_ADD 0xB5 // Request Volume Element Address (O)
-#define SCSI_SENDVOLTAG 0xB6 // Send Volume Tag (O)
-
-//***************************************************************************
-// %%% Commands Unique to Communication Devices %%%
-//***************************************************************************
-#define SCSI_GET_MSG_6 0x08 // Get Message 6-Byte (MANDATORY)
-#define SCSI_GET_MSG_10 0x28 // Get Message 10-Byte (O)
-#define SCSI_GET_MSG_12 0xA8 // Get Message 12-Byte (O)
-#define SCSI_SND_MSG_6 0x0A // Send Message 6-Byte (MANDATORY)
-#define SCSI_SND_MSG_10 0x2A // Send Message 10-Byte (O)
-#define SCSI_SND_MSG_12 0xAA // Send Message 12-Byte (O)
-
-//\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
-//
-// %%% END OF SCSI COMMAND OPCODES %%%
-//
-///\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/
-
-//***************************************************************************
-// %%% Request Sense Data Format %%%
-//***************************************************************************
-typedef struct {
-
- BYTE ErrorCode; // Error Code (70H or 71H)
- BYTE SegmentNum; // Number of current segment descriptor
- BYTE SenseKey; // Sense Key(See bit definitions too)
- BYTE InfoByte0; // Information MSB
- BYTE InfoByte1; // Information MID
- BYTE InfoByte2; // Information MID
- BYTE InfoByte3; // Information LSB
- BYTE AddSenLen; // Additional Sense Length
- BYTE ComSpecInf0; // Command Specific Information MSB
- BYTE ComSpecInf1; // Command Specific Information MID
- BYTE ComSpecInf2; // Command Specific Information MID
- BYTE ComSpecInf3; // Command Specific Information LSB
- BYTE AddSenseCode; // Additional Sense Code
- BYTE AddSenQual; // Additional Sense Code Qualifier
- BYTE FieldRepUCode; // Field Replaceable Unit Code
- BYTE SenKeySpec15; // Sense Key Specific 15th byte
- BYTE SenKeySpec16; // Sense Key Specific 16th byte
- BYTE SenKeySpec17; // Sense Key Specific 17th byte
- BYTE AddSenseBytes; // Additional Sense Bytes
-
-} SENSE_DATA_FMT;
-
-//***************************************************************************
-// %%% REQUEST SENSE ERROR CODE %%%
-//***************************************************************************
-#define SERROR_CURRENT 0x70 // Current Errors
-#define SERROR_DEFERED 0x71 // Deferred Errors
-
-//***************************************************************************
-// %%% REQUEST SENSE BIT DEFINITIONS %%%
-//***************************************************************************
-#define SENSE_VALID 0x80 // Byte 0 Bit 7
-#define SENSE_FILEMRK 0x80 // Byte 2 Bit 7
-#define SENSE_EOM 0x40 // Byte 2 Bit 6
-#define SENSE_ILI 0x20 // Byte 2 Bit 5
-
-//***************************************************************************
-// %%% REQUEST SENSE SENSE KEY DEFINITIONS %%%
-//***************************************************************************
-#define KEY_NOSENSE 0x00 // No Sense
-#define KEY_RECERROR 0x01 // Recovered Error
-#define KEY_NOTREADY 0x02 // Not Ready
-#define KEY_MEDIUMERR 0x03 // Medium Error
-#define KEY_HARDERROR 0x04 // Hardware Error
-#define KEY_ILLGLREQ 0x05 // Illegal Request
-#define KEY_UNITATT 0x06 // Unit Attention
-#define KEY_DATAPROT 0x07 // Data Protect
-#define KEY_BLANKCHK 0x08 // Blank Check
-#define KEY_VENDSPEC 0x09 // Vendor Specific
-#define KEY_COPYABORT 0x0A // Copy Abort
-#define KEY_EQUAL 0x0C // Equal (Search)
-#define KEY_VOLOVRFLW 0x0D // Volume Overflow
-#define KEY_MISCOMP 0x0E // Miscompare (Search)
-#define KEY_RESERVED 0x0F // Reserved
-
-//***************************************************************************
-// %%% PERIPHERAL DEVICE TYPE DEFINITIONS %%%
-//***************************************************************************
-#define DTYPE_DASD 0x00 // Disk Device
-#define DTYPE_SEQD 0x01 // Tape Device
-#define DTYPE_PRNT 0x02 // Printer
-#define DTYPE_PROC 0x03 // Processor
-#define DTYPE_WORM 0x04 // Write-once read-multiple
-#define DTYPE_CROM 0x05 // CD-ROM device
-#define DTYPE_CDROM 0x05 // CD-ROM device
-#define DTYPE_SCAN 0x06 // Scanner device
-#define DTYPE_OPTI 0x07 // Optical memory device
-#define DTYPE_JUKE 0x08 // Medium Changer device
-#define DTYPE_COMM 0x09 // Communications device
-#define DTYPE_RESL 0x0A // Reserved (low)
-#define DTYPE_RESH 0x1E // Reserved (high)
-#define DTYPE_UNKNOWN 0x1F // Unknown or no device type
-
-//***************************************************************************
-// %%% ANSI APPROVED VERSION DEFINITIONS %%%
-//***************************************************************************
-#define ANSI_MAYBE 0x0 // Device may or may not be ANSI approved stand
-#define ANSI_SCSI1 0x1 // Device complies to ANSI X3.131-1986 (SCSI-1)
-#define ANSI_SCSI2 0x2 // Device complies to SCSI-2
-#define ANSI_RESLO 0x3 // Reserved (low)
-#define ANSI_RESHI 0x7 // Reserved (high)
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: scsipt.h,v 1.4 2002/09/16 16:58:36 bdenney Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-//
-// iodev/scsipt.h
-// $Id: scsipt.h,v 1.4 2002/09/16 16:58:36 bdenney Exp $
-//
-// This file was copied from ... ?
-//
-// distilled information from various header files from Microsoft's
-// DDK for Windows NT 4.0
-//
-
-#ifndef _SCSIPT_H_INC
-#define _SCSIPT_H_INC
-
-#include <windows.h>
-
-typedef struct {
- USHORT Length;
- UCHAR ScsiStatus;
- UCHAR PathId;
- UCHAR TargetId;
- UCHAR Lun;
- UCHAR CdbLength;
- UCHAR SenseInfoLength;
- UCHAR DataIn;
- ULONG DataTransferLength;
- ULONG TimeOutValue;
- ULONG DataBufferOffset;
- ULONG SenseInfoOffset;
- UCHAR Cdb[16];
-} SCSI_PASS_THROUGH, *PSCSI_PASS_THROUGH;
-
-
-typedef struct {
- USHORT Length;
- UCHAR ScsiStatus;
- UCHAR PathId;
- UCHAR TargetId;
- UCHAR Lun;
- UCHAR CdbLength;
- UCHAR SenseInfoLength;
- UCHAR DataIn;
- ULONG DataTransferLength;
- ULONG TimeOutValue;
- PVOID DataBuffer;
- ULONG SenseInfoOffset;
- UCHAR Cdb[16];
-} SCSI_PASS_THROUGH_DIRECT, *PSCSI_PASS_THROUGH_DIRECT;
-
-
-typedef struct {
- SCSI_PASS_THROUGH spt;
- ULONG Filler;
- UCHAR ucSenseBuf[32];
- UCHAR ucDataBuf[512];
-} SCSI_PASS_THROUGH_WITH_BUFFERS, *PSCSI_PASS_THROUGH_WITH_BUFFERS;
-
-
-typedef struct {
- SCSI_PASS_THROUGH_DIRECT spt;
- ULONG Filler;
- UCHAR ucSenseBuf[32];
-} SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, *PSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER;
-
-
-
-typedef struct {
- UCHAR NumberOfLogicalUnits;
- UCHAR InitiatorBusId;
- ULONG InquiryDataOffset;
-} SCSI_BUS_DATA, *PSCSI_BUS_DATA;
-
-
-typedef struct {
- UCHAR NumberOfBusses;
- SCSI_BUS_DATA BusData[1];
-} SCSI_ADAPTER_BUS_INFO, *PSCSI_ADAPTER_BUS_INFO;
-
-
-typedef struct {
- UCHAR PathId;
- UCHAR TargetId;
- UCHAR Lun;
- BOOLEAN DeviceClaimed;
- ULONG InquiryDataLength;
- ULONG NextInquiryDataOffset;
- UCHAR InquiryData[1];
-} SCSI_INQUIRY_DATA, *PSCSI_INQUIRY_DATA;
-
-
-typedef struct {
- ULONG Length;
- UCHAR PortNumber;
- UCHAR PathId;
- UCHAR TargetId;
- UCHAR Lun;
-} SCSI_ADDRESS, *PSCSI_ADDRESS;
-
-
-/*
- * method codes
- */
-#define METHOD_BUFFERED 0
-#define METHOD_IN_DIRECT 1
-#define METHOD_OUT_DIRECT 2
-#define METHOD_NEITHER 3
-
-/*
- * file access values
- */
-#define FILE_ANY_ACCESS 0
-#define FILE_READ_ACCESS (0x0001)
-#define FILE_WRITE_ACCESS (0x0002)
-
-
-#define IOCTL_SCSI_BASE 0x00000004
-
-/*
- * constants for DataIn member of SCSI_PASS_THROUGH* structures
- */
-#define SCSI_IOCTL_DATA_OUT 0
-#define SCSI_IOCTL_DATA_IN 1
-#define SCSI_IOCTL_DATA_UNSPECIFIED 2
-
-/*
- * Standard IOCTL define
- */
-#define CTL_CODE( DevType, Function, Method, Access ) ( \
- ((DevType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method) \
-)
-
-#define IOCTL_SCSI_PASS_THROUGH CTL_CODE( IOCTL_SCSI_BASE, 0x0401, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS )
-#define IOCTL_SCSI_MINIPORT CTL_CODE( IOCTL_SCSI_BASE, 0x0402, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS )
-#define IOCTL_SCSI_GET_INQUIRY_DATA CTL_CODE( IOCTL_SCSI_BASE, 0x0403, METHOD_BUFFERED, FILE_ANY_ACCESS)
-#define IOCTL_SCSI_GET_CAPABILITIES CTL_CODE( IOCTL_SCSI_BASE, 0x0404, METHOD_BUFFERED, FILE_ANY_ACCESS)
-#define IOCTL_SCSI_PASS_THROUGH_DIRECT CTL_CODE( IOCTL_SCSI_BASE, 0x0405, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS )
-#define IOCTL_SCSI_GET_ADDRESS CTL_CODE( IOCTL_SCSI_BASE, 0x0406, METHOD_BUFFERED, FILE_ANY_ACCESS )
-
-
-
-#endif
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: serial.cc,v 1.41 2003/11/09 00:14:43 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-// Peter Grehan (grehan@iprg.nokia.com) coded the original version of this
-// serial emulation. He implemented a single 8250, and allow terminal
-// input/output to stdout on FreeBSD.
-// The current version emulates a single 16550A with FIFO. Terminal
-// input/output now works on some more platforms.
-
-
-// Define BX_PLUGGABLE in files that can be compiled into plugins. For
-// platforms that require a special tag on exported symbols, BX_PLUGGABLE
-// is used to know when we are exporting symbols and when we are importing.
-#define BX_PLUGGABLE
-
-#include "bochs.h"
-
-#define LOG_THIS theSerialDevice->
-
-#if USE_RAW_SERIAL
-#include <signal.h>
-#endif
-
-#ifdef WIN32
-#ifndef __MINGW32__
-// +++
-//#include <winsock2.h>
-#include <winsock.h>
-#endif
-#endif
-
-#if defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__linux__) || defined(__GNU__) || defined(__APPLE__)
-#define SERIAL_ENABLE
-#endif
-
-#ifdef SERIAL_ENABLE
-extern "C" {
-#include <termios.h>
-};
-#endif
-
-#ifdef SERIAL_ENABLE
-static struct termios term_orig, term_new;
-#endif
-
-static int tty_id;
-
-bx_serial_c *theSerialDevice = NULL;
-
- int
-libserial_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[])
-{
- theSerialDevice = new bx_serial_c ();
- bx_devices.pluginSerialDevice = theSerialDevice;
- BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theSerialDevice, BX_PLUGIN_SERIAL);
- return(0); // Success
-}
-
- void
-libserial_LTX_plugin_fini(void)
-{
-}
-
-bx_serial_c::bx_serial_c(void)
-{
- put("SER");
- settype(SERLOG);
- tty_id = -1;
- for (int i=0; i<BX_SERIAL_MAXDEV; i++) {
- s[i].tx_timer_index = BX_NULL_TIMER_HANDLE;
- s[i].rx_timer_index = BX_NULL_TIMER_HANDLE;
- s[i].fifo_timer_index = BX_NULL_TIMER_HANDLE;
- }
-}
-
-bx_serial_c::~bx_serial_c(void)
-{
-#ifdef SERIAL_ENABLE
- if ((bx_options.com[0].Oenabled->get ()) && (tty_id >= 0))
- tcsetattr(tty_id, TCSAFLUSH, &term_orig);
-#endif
- // nothing for now
-}
-
-
- void
-bx_serial_c::init(void)
-{
- Bit16u ports[BX_SERIAL_MAXDEV] = {0x03f8, 0x02f8, 0x03e8, 0x02e8};
- char name[16];
-
- if (!bx_options.com[0].Oenabled->get ())
- return;
-
-#ifdef SERIAL_ENABLE
- if (strlen(bx_options.com[0].Odev->getptr ()) > 0) {
- tty_id = open(bx_options.com[0].Odev->getptr (), O_RDWR|O_NONBLOCK,600);
- if (tty_id < 0)
- BX_PANIC(("open of %s (%s) failed\n",
- "com1", bx_options.com[0].Odev->getptr ()));
- BX_DEBUG(("tty_id: %d",tty_id));
- tcgetattr(tty_id, &term_orig);
- bcopy((caddr_t) &term_orig, (caddr_t) &term_new, sizeof(struct termios));
- cfmakeraw(&term_new);
- term_new.c_oflag |= OPOST | ONLCR; // Enable NL to CR-NL translation
-#ifndef TRUE_CTLC
- // ctl-C will exit Bochs, or trap to the debugger
- term_new.c_iflag &= ~IGNBRK;
- term_new.c_iflag |= BRKINT;
- term_new.c_lflag |= ISIG;
-#else
- // ctl-C will be delivered to the serial port
- term_new.c_iflag |= IGNBRK;
- term_new.c_iflag &= ~BRKINT;
-#endif /* !def TRUE_CTLC */
- term_new.c_iflag = 0;
- term_new.c_oflag = 0;
- term_new.c_cflag = CS8|CREAD|CLOCAL;
- term_new.c_lflag = 0;
- term_new.c_cc[VMIN] = 1;
- term_new.c_cc[VTIME] = 0;
- //term_new.c_iflag |= IXOFF;
- tcsetattr(tty_id, TCSAFLUSH, &term_new);
- }
-#endif /* def SERIAL_ENABLE */
- // nothing for now
-#if USE_RAW_SERIAL
- this->raw = new serial_raw("/dev/cua0", SIGUSR1);
-#endif // USE_RAW_SERIAL
-
- /*
- * Put the UART registers into their RESET state
- */
- for (unsigned i=0; i<BX_N_SERIAL_PORTS; i++) {
- if (bx_options.com[i].Oenabled->get ()) {
- sprintf(name, "Serial Port %d", i + 1);
- /* serial interrupt */
- BX_SER_THIS s[i].IRQ = 4 - (i & 1);
- if (i < 2) {
- DEV_register_irq(BX_SER_THIS s[i].IRQ, name);
- }
- /* internal state */
- BX_SER_THIS s[i].ls_ipending = 0;
- BX_SER_THIS s[i].ms_ipending = 0;
- BX_SER_THIS s[i].rx_ipending = 0;
- BX_SER_THIS s[i].fifo_ipending = 0;
- BX_SER_THIS s[i].ls_interrupt = 0;
- BX_SER_THIS s[i].ms_interrupt = 0;
- BX_SER_THIS s[i].rx_interrupt = 0;
- BX_SER_THIS s[i].tx_interrupt = 0;
- BX_SER_THIS s[i].fifo_interrupt = 0;
-
- if (BX_SER_THIS s[i].tx_timer_index == BX_NULL_TIMER_HANDLE) {
- BX_SER_THIS s[i].tx_timer_index =
- bx_pc_system.register_timer(this, tx_timer_handler, 0,
- 0,0, "serial.tx"); // one-shot, inactive
- }
-
- if (BX_SER_THIS s[i].rx_timer_index == BX_NULL_TIMER_HANDLE) {
- BX_SER_THIS s[i].rx_timer_index =
- bx_pc_system.register_timer(this, rx_timer_handler, 0,
- 0,0, "serial.rx"); // one-shot, inactive
- }
- if (BX_SER_THIS s[i].fifo_timer_index == BX_NULL_TIMER_HANDLE) {
- BX_SER_THIS s[i].fifo_timer_index =
- bx_pc_system.register_timer(this, fifo_timer_handler, 0,
- 0,0, "serial.fifo"); // one-shot, inactive
- }
- BX_SER_THIS s[i].rx_pollstate = BX_SER_RXIDLE;
-
- /* int enable: b0000 0000 */
- BX_SER_THIS s[i].int_enable.rxdata_enable = 0;
- BX_SER_THIS s[i].int_enable.txhold_enable = 0;
- BX_SER_THIS s[i].int_enable.rxlstat_enable = 0;
- BX_SER_THIS s[i].int_enable.modstat_enable = 0;
-
- /* int ID: b0000 0001 */
- BX_SER_THIS s[i].int_ident.ipending = 1;
- BX_SER_THIS s[i].int_ident.int_ID = 0;
-
- /* FIFO control: b0000 0000 */
- BX_SER_THIS s[i].fifo_cntl.enable = 0;
- BX_SER_THIS s[i].fifo_cntl.rxtrigger = 0;
- BX_SER_THIS s[i].rx_fifo_end = 0;
- BX_SER_THIS s[i].tx_fifo_end = 0;
-
- /* Line Control reg: b0000 0000 */
- BX_SER_THIS s[i].line_cntl.wordlen_sel = 0;
- BX_SER_THIS s[i].line_cntl.stopbits = 0;
- BX_SER_THIS s[i].line_cntl.parity_enable = 0;
- BX_SER_THIS s[i].line_cntl.evenparity_sel = 0;
- BX_SER_THIS s[i].line_cntl.stick_parity = 0;
- BX_SER_THIS s[i].line_cntl.break_cntl = 0;
- BX_SER_THIS s[i].line_cntl.dlab = 0;
-
- /* Modem Control reg: b0000 0000 */
- BX_SER_THIS s[i].modem_cntl.dtr = 0;
- BX_SER_THIS s[i].modem_cntl.rts = 0;
- BX_SER_THIS s[i].modem_cntl.out1 = 0;
- BX_SER_THIS s[i].modem_cntl.out2 = 0;
- BX_SER_THIS s[i].modem_cntl.local_loopback = 0;
-
- /* Line Status register: b0110 0000 */
- BX_SER_THIS s[i].line_status.rxdata_ready = 0;
- BX_SER_THIS s[i].line_status.overrun_error = 0;
- BX_SER_THIS s[i].line_status.parity_error = 0;
- BX_SER_THIS s[i].line_status.framing_error = 0;
- BX_SER_THIS s[i].line_status.break_int = 0;
- BX_SER_THIS s[i].line_status.thr_empty = 1;
- BX_SER_THIS s[i].line_status.tsr_empty = 1;
- BX_SER_THIS s[i].line_status.fifo_error = 0;
-
- /* Modem Status register: bXXXX 0000 */
- BX_SER_THIS s[i].modem_status.delta_cts = 0;
- BX_SER_THIS s[i].modem_status.delta_dsr = 0;
- BX_SER_THIS s[i].modem_status.ri_trailedge = 0;
- BX_SER_THIS s[i].modem_status.delta_dcd = 0;
- BX_SER_THIS s[i].modem_status.cts = 0;
- BX_SER_THIS s[i].modem_status.dsr = 0;
- BX_SER_THIS s[i].modem_status.ri = 0;
- BX_SER_THIS s[i].modem_status.dcd = 0;
-
- BX_SER_THIS s[i].scratch = 0; /* scratch register */
- BX_SER_THIS s[i].divisor_lsb = 1; /* divisor-lsb register */
- BX_SER_THIS s[i].divisor_msb = 0; /* divisor-msb register */
-
- BX_SER_THIS s[i].baudrate = 115200;
-
- for (unsigned addr=ports[i]; addr<(unsigned)(ports[i]+8); addr++) {
- BX_DEBUG(("register read/write: 0x%04x",addr));
- DEV_register_ioread_handler(this, read_handler, addr, name, 1);
- DEV_register_iowrite_handler(this, write_handler, addr, name, 1);
- }
- BX_INFO(("com%d at 0x%04x irq %d", i+1, ports[i], BX_SER_THIS s[i].IRQ));
- }
- }
-}
-
- void
-bx_serial_c::reset(unsigned type)
-{
-}
-
- void
-bx_serial_c::lower_interrupt(Bit8u port)
-{
- /* If there are no more ints pending, clear the irq */
- if ((BX_SER_THIS s[port].rx_interrupt == 0) &&
- (BX_SER_THIS s[port].tx_interrupt == 0) &&
- (BX_SER_THIS s[port].ls_interrupt == 0) &&
- (BX_SER_THIS s[port].ms_interrupt == 0) &&
- (BX_SER_THIS s[port].fifo_interrupt == 0)) {
- DEV_pic_lower_irq(BX_SER_THIS s[port].IRQ);
- }
-}
-
- void
-bx_serial_c::raise_interrupt(Bit8u port, int type)
-{
- bx_bool gen_int = 0;
-
- switch (type) {
- case BX_SER_INT_IER: /* IER has changed */
- gen_int = 1;
- break;
- case BX_SER_INT_RXDATA:
- if (BX_SER_THIS s[port].int_enable.rxdata_enable) {
- BX_SER_THIS s[port].rx_interrupt = 1;
- gen_int = 1;
- } else {
- BX_SER_THIS s[port].rx_ipending = 1;
- }
- break;
- case BX_SER_INT_TXHOLD:
- if (BX_SER_THIS s[port].int_enable.txhold_enable) {
- BX_SER_THIS s[port].tx_interrupt = 1;
- gen_int = 1;
- }
- break;
- case BX_SER_INT_RXLSTAT:
- if (BX_SER_THIS s[port].int_enable.rxlstat_enable) {
- BX_SER_THIS s[port].ls_interrupt = 1;
- gen_int = 1;
- } else {
- BX_SER_THIS s[port].ls_ipending = 1;
- }
- break;
- case BX_SER_INT_MODSTAT:
- if ((BX_SER_THIS s[port].ms_ipending == 1) &&
- (BX_SER_THIS s[port].int_enable.modstat_enable == 1)) {
- BX_SER_THIS s[port].ms_interrupt = 1;
- BX_SER_THIS s[port].ms_ipending = 0;
- gen_int = 1;
- }
- break;
- case BX_SER_INT_FIFO:
- if (BX_SER_THIS s[port].int_enable.rxdata_enable) {
- BX_SER_THIS s[port].fifo_interrupt = 1;
- gen_int = 1;
- } else {
- BX_SER_THIS s[port].fifo_ipending = 1;
- }
- break;
- }
- if (gen_int && BX_SER_THIS s[port].modem_cntl.out2) {
- DEV_pic_raise_irq(BX_SER_THIS s[port].IRQ);
- }
-}
-
- // static IO port read callback handler
- // redirects to non-static class handler to avoid virtual functions
-
- Bit32u
-bx_serial_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len)
-{
-#if !BX_USE_SER_SMF
- bx_serial_c *class_ptr = (bx_serial_c *) this_ptr;
-
- return( class_ptr->read(address, io_len) );
-}
-
-
- Bit32u
-bx_serial_c::read(Bit32u address, unsigned io_len)
-{
-#else
- UNUSED(this_ptr);
-#endif // !BX_USE_SER_SMF
- //UNUSED(address);
- Bit8u val;
-
- /* SERIAL PORT 1 */
-
- BX_DEBUG(("register read from address 0x%04x - ", (unsigned) address));
-
- switch (address) {
- case 0x03F8: /* receive buffer, or divisor latch LSB if DLAB set */
- if (BX_SER_THIS s[0].line_cntl.dlab) {
- val = BX_SER_THIS s[0].divisor_lsb;
- } else {
- if (BX_SER_THIS s[0].fifo_cntl.enable) {
- val = BX_SER_THIS s[0].rx_fifo[0];
- if (BX_SER_THIS s[0].rx_fifo_end > 0) {
- memcpy(&BX_SER_THIS s[0].rx_fifo[0], &BX_SER_THIS s[0].rx_fifo[1], 15);
- BX_SER_THIS s[0].rx_fifo_end--;
- }
- if (BX_SER_THIS s[0].rx_fifo_end == 0) {
- BX_SER_THIS s[0].line_status.rxdata_ready = 0;
- BX_SER_THIS s[0].rx_interrupt = 0;
- BX_SER_THIS s[0].rx_ipending = 0;
- BX_SER_THIS s[0].fifo_interrupt = 0;
- BX_SER_THIS s[0].fifo_ipending = 0;
- lower_interrupt(0);
- }
- } else {
- val = BX_SER_THIS s[0].rxbuffer;
- BX_SER_THIS s[0].line_status.rxdata_ready = 0;
- BX_SER_THIS s[0].rx_interrupt = 0;
- BX_SER_THIS s[0].rx_ipending = 0;
- lower_interrupt(0);
- }
- }
- break;
-
- case 0x03F9: /* interrupt enable register, or div. latch MSB */
- if (BX_SER_THIS s[0].line_cntl.dlab) {
- val = BX_SER_THIS s[0].divisor_msb;
- } else {
- val = BX_SER_THIS s[0].int_enable.rxdata_enable |
- (BX_SER_THIS s[0].int_enable.txhold_enable << 1) |
- (BX_SER_THIS s[0].int_enable.rxlstat_enable << 2) |
- (BX_SER_THIS s[0].int_enable.modstat_enable << 3);
- }
- break;
-
- case 0x03FA: /* interrupt ID register */
- /*
- * Set the interrupt ID based on interrupt source
- */
- if (BX_SER_THIS s[0].ls_interrupt) {
- BX_SER_THIS s[0].int_ident.int_ID = 0x3;
- BX_SER_THIS s[0].int_ident.ipending = 0;
- } else if (BX_SER_THIS s[0].fifo_interrupt) {
- BX_SER_THIS s[0].int_ident.int_ID = 0x6;
- BX_SER_THIS s[0].int_ident.ipending = 0;
- } else if (BX_SER_THIS s[0].rx_interrupt) {
- BX_SER_THIS s[0].int_ident.int_ID = 0x2;
- BX_SER_THIS s[0].int_ident.ipending = 0;
- } else if (BX_SER_THIS s[0].tx_interrupt) {
- BX_SER_THIS s[0].int_ident.int_ID = 0x1;
- BX_SER_THIS s[0].int_ident.ipending = 0;
- } else if (BX_SER_THIS s[0].ms_interrupt) {
- BX_SER_THIS s[0].int_ident.int_ID = 0x0;
- BX_SER_THIS s[0].int_ident.ipending = 0;
- } else {
- BX_SER_THIS s[0].int_ident.int_ID = 0x0;
- BX_SER_THIS s[0].int_ident.ipending = 1;
- }
- BX_SER_THIS s[0].tx_interrupt = 0;
- lower_interrupt(0);
-
- val = BX_SER_THIS s[0].int_ident.ipending |
- (BX_SER_THIS s[0].int_ident.int_ID << 1) |
- (BX_SER_THIS s[0].fifo_cntl.enable ? 0xc0 : 0x00);
- break;
-
- case 0x03FB: /* Line control register */
- val = BX_SER_THIS s[0].line_cntl.wordlen_sel |
- (BX_SER_THIS s[0].line_cntl.stopbits << 2) |
- (BX_SER_THIS s[0].line_cntl.parity_enable << 3) |
- (BX_SER_THIS s[0].line_cntl.evenparity_sel << 4) |
- (BX_SER_THIS s[0].line_cntl.stick_parity << 5) |
- (BX_SER_THIS s[0].line_cntl.break_cntl << 6) |
- (BX_SER_THIS s[0].line_cntl.dlab << 7);
- break;
-
- case 0x03FC: /* MODEM control register */
- val = BX_SER_THIS s[0].modem_cntl.dtr |
- (BX_SER_THIS s[0].modem_cntl.rts << 1) |
- (BX_SER_THIS s[0].modem_cntl.out1 << 2) |
- (BX_SER_THIS s[0].modem_cntl.out2 << 3) |
- (BX_SER_THIS s[0].modem_cntl.local_loopback << 4);
- break;
-
- case 0x03FD: /* Line status register */
- val = BX_SER_THIS s[0].line_status.rxdata_ready |
- (BX_SER_THIS s[0].line_status.overrun_error << 1) |
- (BX_SER_THIS s[0].line_status.parity_error << 2) |
- (BX_SER_THIS s[0].line_status.framing_error << 3) |
- (BX_SER_THIS s[0].line_status.break_int << 4) |
- (BX_SER_THIS s[0].line_status.thr_empty << 5) |
- (BX_SER_THIS s[0].line_status.tsr_empty << 6) |
- (BX_SER_THIS s[0].line_status.fifo_error << 7);
- BX_SER_THIS s[0].line_status.overrun_error = 0;
- BX_SER_THIS s[0].line_status.break_int = 0;
- BX_SER_THIS s[0].ls_interrupt = 0;
- BX_SER_THIS s[0].ls_ipending = 0;
- lower_interrupt(0);
- break;
-
- case 0x03FE: /* MODEM status register */
- val = BX_SER_THIS s[0].modem_status.delta_cts |
- (BX_SER_THIS s[0].modem_status.delta_dsr << 1) |
- (BX_SER_THIS s[0].modem_status.ri_trailedge << 2) |
- (BX_SER_THIS s[0].modem_status.delta_dcd << 3) |
- (BX_SER_THIS s[0].modem_status.cts << 4) |
- (BX_SER_THIS s[0].modem_status.dsr << 5) |
- (BX_SER_THIS s[0].modem_status.ri << 6) |
- (BX_SER_THIS s[0].modem_status.dcd << 7);
- BX_SER_THIS s[0].modem_status.delta_cts = 0;
- BX_SER_THIS s[0].modem_status.delta_dsr = 0;
- BX_SER_THIS s[0].modem_status.ri_trailedge = 0;
- BX_SER_THIS s[0].modem_status.delta_dcd = 0;
- BX_SER_THIS s[0].ms_interrupt = 0;
- BX_SER_THIS s[0].ms_ipending = 0;
- lower_interrupt(0);
- break;
-
- case 0x03FF: /* scratch register */
- val = BX_SER_THIS s[0].scratch;
- break;
-
- default:
- val = 0; // keep compiler happy
- BX_PANIC(("unsupported io read from address=0x%04x!",
- (unsigned) address));
- break;
- }
-
- BX_DEBUG(("val = 0x%02x", (unsigned) val));
-
- return(val);
-}
-
-
- // static IO port write callback handler
- // redirects to non-static class handler to avoid virtual functions
-
-void
-bx_serial_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len)
-{
-#if !BX_USE_SER_SMF
- bx_serial_c *class_ptr = (bx_serial_c *) this_ptr;
-
- class_ptr->write(address, value, io_len);
-}
-
-void
-bx_serial_c::write(Bit32u address, Bit32u value, unsigned io_len)
-{
-#else
- UNUSED(this_ptr);
-#endif // !BX_USE_SER_SMF
- bx_bool prev_cts, prev_dsr, prev_ri, prev_dcd;
- bx_bool new_rx_ien, new_tx_ien, new_ls_ien, new_ms_ien;
- bx_bool gen_int = 0;
-
- /* SERIAL PORT 1 */
-
- BX_DEBUG(("write to address: 0x%04x = 0x%02x",
- (unsigned) address, (unsigned) value));
-
- switch (address) {
- case 0x03F8: /* transmit buffer, or divisor latch LSB if DLAB set */
- if (BX_SER_THIS s[0].line_cntl.dlab) {
- BX_SER_THIS s[0].divisor_lsb = value;
-
- if ((value != 0) || (BX_SER_THIS s[0].divisor_msb != 0)) {
- BX_SER_THIS s[0].baudrate = (int) (BX_PC_CLOCK_XTL /
- (16 * ((BX_SER_THIS s[0].divisor_msb << 8) |
- BX_SER_THIS s[0].divisor_lsb)));
-#if USE_RAW_SERIAL
- BX_SER_THIS raw->set_baudrate(BX_SER_THIS s[0].baudrate);
-#endif // USE_RAW_SERIAL
- }
- } else {
- Bit8u bitmask = 0xff >> (3 - BX_SER_THIS s[0].line_cntl.wordlen_sel);
- if (BX_SER_THIS s[0].line_status.thr_empty) {
- if (BX_SER_THIS s[0].fifo_cntl.enable) {
- BX_SER_THIS s[0].tx_fifo[BX_SER_THIS s[0].tx_fifo_end++] = value & bitmask;
- } else {
- BX_SER_THIS s[0].thrbuffer = value & bitmask;
- }
- BX_SER_THIS s[0].line_status.thr_empty = 0;
- if (BX_SER_THIS s[0].line_status.tsr_empty) {
- if (BX_SER_THIS s[0].fifo_cntl.enable) {
- BX_SER_THIS s[0].tsrbuffer = BX_SER_THIS s[0].tx_fifo[0];
- memcpy(&BX_SER_THIS s[0].tx_fifo[0], &BX_SER_THIS s[0].tx_fifo[1], 15);
- BX_SER_THIS s[0].line_status.thr_empty = (--BX_SER_THIS s[0].tx_fifo_end == 0);
- } else {
- BX_SER_THIS s[0].tsrbuffer = BX_SER_THIS s[0].thrbuffer;
- BX_SER_THIS s[0].line_status.thr_empty = 1;
- }
- BX_SER_THIS s[0].line_status.tsr_empty = 0;
- raise_interrupt(0, BX_SER_INT_TXHOLD);
- bx_pc_system.activate_timer(BX_SER_THIS s[0].tx_timer_index,
- (int) (1000000.0 / BX_SER_THIS s[0].baudrate *
- (BX_SER_THIS s[0].line_cntl.wordlen_sel + 5)),
- 0); /* not continuous */
- } else {
- BX_SER_THIS s[0].tx_interrupt = 0;
- lower_interrupt(0);
- }
- } else {
- if (BX_SER_THIS s[0].fifo_cntl.enable) {
- if (BX_SER_THIS s[0].tx_fifo_end < 16) {
- BX_SER_THIS s[0].tx_fifo[BX_SER_THIS s[0].tx_fifo_end++] = value & bitmask;
- } else {
- BX_ERROR(("com1: transmit FIFO overflow"));
- }
- } else {
- BX_ERROR(("write to tx hold register when not empty"));
- }
- }
- }
- break;
-
- case 0x03F9: /* interrupt enable register, or div. latch MSB */
- if (BX_SER_THIS s[0].line_cntl.dlab) {
- BX_SER_THIS s[0].divisor_msb = value;
-
- if ((value != 0) || (BX_SER_THIS s[0].divisor_lsb != 0)) {
- BX_SER_THIS s[0].baudrate = (int) (BX_PC_CLOCK_XTL /
- (16 * ((BX_SER_THIS s[0].divisor_msb << 8) |
- BX_SER_THIS s[0].divisor_lsb)));
-#if USE_RAW_SERIAL
- BX_SER_THIS raw->set_baudrate(BX_SER_THIS s[0].baudrate);
-#endif // USE_RAW_SERIAL
- }
- } else {
- new_rx_ien = value & 0x01;
- new_tx_ien = (value & 0x02) >> 1;
- new_ls_ien = (value & 0x04) >> 2;
- new_ms_ien = (value & 0x08) >> 3;
- if (new_ms_ien != BX_SER_THIS s[0].int_enable.modstat_enable) {
- BX_SER_THIS s[0].int_enable.modstat_enable = new_ms_ien;
- if (BX_SER_THIS s[0].int_enable.modstat_enable == 1) {
- if (BX_SER_THIS s[0].ms_ipending == 1) {
- BX_SER_THIS s[0].ms_interrupt = 1;
- BX_SER_THIS s[0].ms_ipending = 0;
- gen_int = 1;
- }
- } else {
- if (BX_SER_THIS s[0].ms_interrupt == 1) {
- BX_SER_THIS s[0].ms_interrupt = 0;
- BX_SER_THIS s[0].ms_ipending = 1;
- lower_interrupt(0);
- }
- }
- }
- if (new_tx_ien != BX_SER_THIS s[0].int_enable.txhold_enable) {
- BX_SER_THIS s[0].int_enable.txhold_enable = new_tx_ien;
- if (BX_SER_THIS s[0].int_enable.txhold_enable == 1) {
- BX_SER_THIS s[0].tx_interrupt = BX_SER_THIS s[0].line_status.thr_empty;
- if (BX_SER_THIS s[0].tx_interrupt) gen_int = 1;
- } else {
- BX_SER_THIS s[0].tx_interrupt = 0;
- lower_interrupt(0);
- }
- }
- if (new_rx_ien != BX_SER_THIS s[0].int_enable.rxdata_enable) {
- BX_SER_THIS s[0].int_enable.rxdata_enable = new_rx_ien;
- if (BX_SER_THIS s[0].int_enable.rxdata_enable == 1) {
- if (BX_SER_THIS s[0].fifo_ipending == 1) {
- BX_SER_THIS s[0].fifo_interrupt = 1;
- BX_SER_THIS s[0].fifo_ipending = 0;
- gen_int = 1;
- }
- if (BX_SER_THIS s[0].rx_ipending == 1) {
- BX_SER_THIS s[0].rx_interrupt = 1;
- BX_SER_THIS s[0].rx_ipending = 0;
- gen_int = 1;
- }
- } else {
- if (BX_SER_THIS s[0].rx_interrupt == 1) {
- BX_SER_THIS s[0].rx_interrupt = 0;
- BX_SER_THIS s[0].rx_ipending = 1;
- lower_interrupt(0);
- }
- if (BX_SER_THIS s[0].fifo_interrupt == 1) {
- BX_SER_THIS s[0].fifo_interrupt = 0;
- BX_SER_THIS s[0].fifo_ipending = 1;
- lower_interrupt(0);
- }
- }
- }
- if (new_ls_ien != BX_SER_THIS s[0].int_enable.rxlstat_enable) {
- BX_SER_THIS s[0].int_enable.rxlstat_enable = new_ls_ien;
- if (BX_SER_THIS s[0].int_enable.rxlstat_enable == 1) {
- if (BX_SER_THIS s[0].ls_ipending == 1) {
- BX_SER_THIS s[0].ls_interrupt = 1;
- BX_SER_THIS s[0].ls_ipending = 0;
- gen_int = 1;
- }
- } else {
- if (BX_SER_THIS s[0].ls_interrupt == 1) {
- BX_SER_THIS s[0].ls_interrupt = 0;
- BX_SER_THIS s[0].ls_ipending = 1;
- lower_interrupt(0);
- }
- }
- }
- if (gen_int) raise_interrupt(0, BX_SER_INT_IER);
- }
- break;
-
- case 0x03FA: /* FIFO control register */
- if (!BX_SER_THIS s[0].fifo_cntl.enable && (value & 0x01)) {
- BX_INFO(("FIFO enabled"));
- BX_SER_THIS s[0].rx_fifo_end = 0;
- BX_SER_THIS s[0].tx_fifo_end = 0;
- }
- BX_SER_THIS s[0].fifo_cntl.enable = value & 0x01;
- if (value & 0x02) {
- BX_SER_THIS s[0].rx_fifo_end = 0;
- }
- if (value & 0x04) {
- BX_SER_THIS s[0].tx_fifo_end = 0;
- }
- BX_SER_THIS s[0].fifo_cntl.rxtrigger = (value & 0xc0) >> 6;
- break;
-
- case 0x03FB: /* Line control register */
-#if !USE_RAW_SERIAL
- if ((value & 0x3) != 0x3) {
- /* ignore this: this is set by FreeBSD when the console
- code wants to set DLAB */
- }
-#endif // !USE_RAW_SERIAL
-#if USE_RAW_SERIAL
- if (BX_SER_THIS s[0].line_cntl.wordlen_sel != (value & 0x3)) {
- BX_SER_THIS raw->set_data_bits((value & 0x3) + 5);
- }
- if (BX_SER_THIS s[0].line_cntl.stopbits != (value & 0x4) >> 2) {
- BX_SER_THIS raw->set_stop_bits((value & 0x4 >> 2) ? 2 : 1);
- }
- if (BX_SER_THIS s[0].line_cntl.parity_enable != (value & 0x8) >> 3 ||
- BX_SER_THIS s[0].line_cntl.evenparity_sel != (value & 0x10) >> 4 ||
- BX_SER_THIS s[0].line_cntl.stick_parity != (value & 0x20) >> 5) {
- if (((value & 0x20) >> 5) &&
- ((value & 0x8) >> 3))
- BX_PANIC(("sticky parity set and parity enabled"));
- BX_SER_THIS raw->set_parity_mode(((value & 0x8) >> 3),
- ((value & 0x10) >> 4) ? P_EVEN : P_ODD);
- }
- if (BX_SER_THIS s[0].line_cntl.break_cntl && !((value & 0x40) >> 6)) {
- BX_SER_THIS raw->transmit(C_BREAK);
- }
-#endif // USE_RAW_SERIAL
-
- BX_SER_THIS s[0].line_cntl.wordlen_sel = value & 0x3;
- /* These are ignored, but set them up so they can be read back */
- BX_SER_THIS s[0].line_cntl.stopbits = (value & 0x4) >> 2;
- BX_SER_THIS s[0].line_cntl.parity_enable = (value & 0x8) >> 3;
- BX_SER_THIS s[0].line_cntl.evenparity_sel = (value & 0x10) >> 4;
- BX_SER_THIS s[0].line_cntl.stick_parity = (value & 0x20) >> 5;
- BX_SER_THIS s[0].line_cntl.break_cntl = (value & 0x40) >> 6;
- /* used when doing future writes */
- if (BX_SER_THIS s[0].line_cntl.dlab &&
- !((value & 0x80) >> 7)) {
- // Start the receive polling process if not already started
- // and there is a valid baudrate.
- if (BX_SER_THIS s[0].rx_pollstate == BX_SER_RXIDLE &&
- BX_SER_THIS s[0].baudrate != 0) {
- BX_SER_THIS s[0].rx_pollstate = BX_SER_RXPOLL;
- bx_pc_system.activate_timer(BX_SER_THIS s[0].rx_timer_index,
- (int) (1000000.0 / BX_SER_THIS s[0].baudrate *
- (BX_SER_THIS s[0].line_cntl.wordlen_sel + 5)),
- 0); /* not continuous */
- }
- BX_DEBUG(("baud rate set - %d", BX_SER_THIS s[0].baudrate));
- }
- BX_SER_THIS s[0].line_cntl.dlab = (value & 0x80) >> 7;
- break;
-
- case 0x03FC: /* MODEM control register */
- if ((value & 0x01) == 0) {
-#if USE_RAW_SERIAL
- BX_SER_THIS raw->send_hangup();
-#endif
- }
-
- BX_SER_THIS s[0].modem_cntl.dtr = value & 0x01;
- BX_SER_THIS s[0].modem_cntl.rts = (value & 0x02) >> 1;
- BX_SER_THIS s[0].modem_cntl.out1 = (value & 0x04) >> 2;
- BX_SER_THIS s[0].modem_cntl.out2 = (value & 0x08) >> 3;
- BX_SER_THIS s[0].modem_cntl.local_loopback = (value & 0x10) >> 4;
-
- if (BX_SER_THIS s[0].modem_cntl.local_loopback) {
- prev_cts = BX_SER_THIS s[0].modem_status.cts;
- prev_dsr = BX_SER_THIS s[0].modem_status.dsr;
- prev_ri = BX_SER_THIS s[0].modem_status.ri;
- prev_dcd = BX_SER_THIS s[0].modem_status.dcd;
- BX_SER_THIS s[0].modem_status.cts = BX_SER_THIS s[0].modem_cntl.rts;
- BX_SER_THIS s[0].modem_status.dsr = BX_SER_THIS s[0].modem_cntl.dtr;
- BX_SER_THIS s[0].modem_status.ri = BX_SER_THIS s[0].modem_cntl.out1;
- BX_SER_THIS s[0].modem_status.dcd = BX_SER_THIS s[0].modem_cntl.out2;
- if (BX_SER_THIS s[0].modem_status.cts != prev_cts) {
- BX_SER_THIS s[0].modem_status.delta_cts = 1;
- BX_SER_THIS s[0].ms_ipending = 1;
- }
- if (BX_SER_THIS s[0].modem_status.dsr != prev_dsr) {
- BX_SER_THIS s[0].modem_status.delta_dsr = 1;
- BX_SER_THIS s[0].ms_ipending = 1;
- }
- if (BX_SER_THIS s[0].modem_status.ri != prev_ri)
- BX_SER_THIS s[0].ms_ipending = 1;
- if ((BX_SER_THIS s[0].modem_status.ri == 0) && (prev_ri == 1))
- BX_SER_THIS s[0].modem_status.ri_trailedge = 1;
- if (BX_SER_THIS s[0].modem_status.dcd != prev_dcd) {
- BX_SER_THIS s[0].modem_status.delta_dcd = 1;
- BX_SER_THIS s[0].ms_ipending = 1;
- }
- raise_interrupt(0, BX_SER_INT_MODSTAT);
- } else {
- /* set these to 0 for the time being */
- BX_SER_THIS s[0].modem_status.cts = 0;
- BX_SER_THIS s[0].modem_status.dsr = 0;
- BX_SER_THIS s[0].modem_status.ri = 0;
- BX_SER_THIS s[0].modem_status.dcd = 0;
- }
- break;
-
- case 0x03FD: /* Line status register */
- BX_ERROR(("write to line status register ignored"));
- break;
-
- case 0x03FE: /* MODEM status register */
- BX_ERROR(("write to MODEM status register ignored"));
- break;
-
- case 0x03FF: /* scratch register */
- BX_SER_THIS s[0].scratch = value;
- break;
-
- default:
- BX_PANIC(("unsupported io write to address=0x%04x, value = 0x%02x!",
- (unsigned) address, (unsigned) value));
- break;
- }
-}
-
-
-void
-bx_serial_c::rx_fifo_enq(Bit8u port, Bit8u data)
-{
- bx_bool gen_int = 0;
-
- if (BX_SER_THIS s[port].fifo_cntl.enable) {
- if (BX_SER_THIS s[port].rx_fifo_end == 16) {
- BX_ERROR(("com%d: receive FIFO overflow", port + 1));
- BX_SER_THIS s[port].line_status.overrun_error = 1;
- raise_interrupt(port, BX_SER_INT_RXLSTAT);
- } else {
- BX_SER_THIS s[port].rx_fifo[BX_SER_THIS s[0].rx_fifo_end++] = data;
- switch (BX_SER_THIS s[port].fifo_cntl.rxtrigger) {
- case 1:
- if (BX_SER_THIS s[0].rx_fifo_end == 4) gen_int = 1;
- break;
- case 2:
- if (BX_SER_THIS s[0].rx_fifo_end == 8) gen_int = 1;
- break;
- case 3:
- if (BX_SER_THIS s[0].rx_fifo_end == 14) gen_int = 1;
- break;
- default:
- gen_int = 1;
- }
- if (gen_int) {
- bx_pc_system.deactivate_timer(BX_SER_THIS s[0].fifo_timer_index);
- BX_SER_THIS s[port].line_status.rxdata_ready = 1;
- raise_interrupt(port, BX_SER_INT_RXDATA);
- } else {
- bx_pc_system.activate_timer(BX_SER_THIS s[0].fifo_timer_index,
- (int) (1000000.0 / BX_SER_THIS s[0].baudrate *
- (BX_SER_THIS s[0].line_cntl.wordlen_sel + 5) * 16),
- 0); /* not continuous */
- }
- }
- } else {
- if (BX_SER_THIS s[port].line_status.rxdata_ready == 1) {
- BX_ERROR(("com%d: overrun error", port + 1));
- BX_SER_THIS s[port].line_status.overrun_error = 1;
- raise_interrupt(port, BX_SER_INT_RXLSTAT);
- }
- BX_SER_THIS s[port].rxbuffer = data;
- BX_SER_THIS s[port].line_status.rxdata_ready = 1;
- raise_interrupt(port, BX_SER_INT_RXDATA);
- }
-}
-
-
-void
-bx_serial_c::tx_timer_handler(void *this_ptr)
-{
- bx_serial_c *class_ptr = (bx_serial_c *) this_ptr;
-
- class_ptr->tx_timer();
-}
-
-
-void
-bx_serial_c::tx_timer(void)
-{
- bx_bool gen_int = 0;
-
- if (BX_SER_THIS s[0].modem_cntl.local_loopback) {
- rx_fifo_enq(0, BX_SER_THIS s[0].tsrbuffer);
- } else {
-#if USE_RAW_SERIAL
- if (!BX_SER_THIS raw->ready_transmit())
- BX_PANIC(("Not ready to transmit"));
- BX_SER_THIS raw->transmit(BX_SER_THIS s[0].tsrbuffer);
-#endif
-#if defined(SERIAL_ENABLE)
- BX_DEBUG(("write: '%c'", BX_SER_THIS s[0].tsrbuffer));
- if (tty_id >= 0) write(tty_id, (bx_ptr_t) & BX_SER_THIS s[0].tsrbuffer, 1);
-#endif
- }
-
- BX_SER_THIS s[0].line_status.tsr_empty = 1;
- if (BX_SER_THIS s[0].fifo_cntl.enable && (BX_SER_THIS s[0].tx_fifo_end > 0)) {
- BX_SER_THIS s[0].tsrbuffer = BX_SER_THIS s[0].tx_fifo[0];
- BX_SER_THIS s[0].line_status.tsr_empty = 0;
- memcpy(&BX_SER_THIS s[0].tx_fifo[0], &BX_SER_THIS s[0].tx_fifo[1], 15);
- gen_int = (--BX_SER_THIS s[0].tx_fifo_end == 0);
- } else if (!BX_SER_THIS s[0].line_status.thr_empty) {
- BX_SER_THIS s[0].tsrbuffer = BX_SER_THIS s[0].thrbuffer;
- BX_SER_THIS s[0].line_status.tsr_empty = 0;
- gen_int = 1;
- }
- if (!BX_SER_THIS s[0].line_status.tsr_empty) {
- if (gen_int) {
- BX_SER_THIS s[0].line_status.thr_empty = 1;
- raise_interrupt(0, BX_SER_INT_TXHOLD);
- }
- bx_pc_system.activate_timer(BX_SER_THIS s[0].tx_timer_index,
- (int) (1000000.0 / BX_SER_THIS s[0].baudrate *
- (BX_SER_THIS s[0].line_cntl.wordlen_sel + 5)),
- 0); /* not continuous */
- }
-}
-
-
-void
-bx_serial_c::rx_timer_handler(void *this_ptr)
-{
- bx_serial_c *class_ptr = (bx_serial_c *) this_ptr;
-
- class_ptr->rx_timer();
-}
-
-
-void
-bx_serial_c::rx_timer(void)
-{
-#if BX_HAVE_SELECT
-#ifndef __BEOS__
- struct timeval tval;
- fd_set fds;
-#endif
-#endif
- int bdrate = BX_SER_THIS s[0].baudrate / (BX_SER_THIS s[0].line_cntl.wordlen_sel + 5);
- unsigned char chbuf = 0;
-
-#if BX_HAVE_SELECT
-#ifndef __BEOS__
- tval.tv_sec = 0;
- tval.tv_usec = 0;
-
-// MacOS: I'm not sure what to do with this, since I don't know
-// what an fd_set is or what FD_SET() or select() do. They aren't
-// declared in the CodeWarrior standard library headers. I'm just
-// leaving it commented out for the moment.
-
- FD_ZERO(&fds);
- if (tty_id >= 0) FD_SET(tty_id, &fds);
-
- if ((BX_SER_THIS s[0].line_status.rxdata_ready == 0) ||
- (BX_SER_THIS s[0].fifo_cntl.enable)) {
-#if USE_RAW_SERIAL
- bx_bool rdy;
- uint16 data;
- if ((rdy = BX_SER_THIS raw->ready_receive())) {
- data = BX_SER_THIS raw->receive();
- if (data == C_BREAK) {
- BX_DEBUG(("got BREAK"));
- BX_SER_THIS s[0].line_status.break_int = 1;
- rdy = 0;
- }
- }
- if (rdy) {
- chbuf = data;
-#elif defined(SERIAL_ENABLE)
- if ((tty_id >= 0) && (select(tty_id + 1, &fds, NULL, NULL, &tval) == 1)) {
- (void) read(tty_id, &chbuf, 1);
- BX_DEBUG(("read: '%c'",chbuf));
-#else
- if (0) {
-#endif
- if (!BX_SER_THIS s[0].modem_cntl.local_loopback) {
- rx_fifo_enq(0, chbuf);
- }
- } else {
- if (!BX_SER_THIS s[0].fifo_cntl.enable) {
- bdrate = (int) (1000000.0 / 100000); // Poll frequency is 100ms
- }
- }
- } else {
- // Poll at 4x baud rate to see if the next-char can
- // be read
- bdrate *= 4;
- }
-#endif
-#endif
-
- bx_pc_system.activate_timer(BX_SER_THIS s[0].rx_timer_index,
- (int) (1000000.0 / bdrate),
- 0); /* not continuous */
-}
-
-
-void
-bx_serial_c::fifo_timer_handler(void *this_ptr)
-{
- bx_serial_c *class_ptr = (bx_serial_c *) this_ptr;
-
- class_ptr->fifo_timer();
-}
-
-
-void
-bx_serial_c::fifo_timer(void)
-{
- BX_SER_THIS s[0].line_status.rxdata_ready = 1;
- raise_interrupt(0, BX_SER_INT_FIFO);
-}
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: serial.h,v 1.15 2003/11/16 08:21:10 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-// Peter Grehan (grehan@iprg.nokia.com) coded most of this
-// serial emulation.
-
-#if USE_RAW_SERIAL
-#include "serial_raw.h"
-#endif // USE_RAW_SERIAL
-
-#if BX_USE_SER_SMF
-# define BX_SER_SMF static
-# define BX_SER_THIS theSerialDevice->
-#else
-# define BX_SER_SMF
-# define BX_SER_THIS this->
-#endif
-
-#define BX_SERIAL_MAXDEV 4
-
-#define BX_PC_CLOCK_XTL 1843200.0
-
-#define BX_SER_RXIDLE 0
-#define BX_SER_RXPOLL 1
-#define BX_SER_RXWAIT 2
-
-enum {
- BX_SER_INT_IER,
- BX_SER_INT_RXDATA,
- BX_SER_INT_TXHOLD,
- BX_SER_INT_RXLSTAT,
- BX_SER_INT_MODSTAT,
- BX_SER_INT_FIFO
-};
-
-typedef struct {
- /*
- * UART internal state
- */
- bx_bool ls_interrupt;
- bx_bool ms_interrupt;
- bx_bool rx_interrupt;
- bx_bool tx_interrupt;
- bx_bool fifo_interrupt;
- bx_bool ls_ipending;
- bx_bool ms_ipending;
- bx_bool rx_ipending;
- bx_bool fifo_ipending;
-
- Bit8u IRQ;
-
- Bit8u rx_fifo_end;
- Bit8u tx_fifo_end;
-
- int baudrate;
- int tx_timer_index;
-
- int rx_pollstate;
- int rx_timer_index;
- int fifo_timer_index;
-
- /*
- * Register definitions
- */
- Bit8u rxbuffer; /* receiver buffer register (r/o) */
- Bit8u thrbuffer; /* transmit holding register (w/o) */
- /* Interrupt Enable Register */
- struct {
- bx_bool rxdata_enable; /* 1=enable receive data interrupts */
- bx_bool txhold_enable; /* 1=enable tx. holding reg. empty ints */
- bx_bool rxlstat_enable; /* 1=enable rx line status interrupts */
- bx_bool modstat_enable; /* 1=enable modem status interrupts */
- } int_enable;
- /* Interrupt Identification Register (r/o) */
- struct {
- bx_bool ipending; /* 0=interrupt pending */
- Bit8u int_ID; /* 3-bit interrupt ID */
- } int_ident;
- /* FIFO Control Register (w/o) */
- struct {
- bx_bool enable; /* 1=enable tx and rx FIFOs */
- Bit8u rxtrigger; /* 2-bit code for rx fifo trigger level */
- } fifo_cntl;
- /* Line Control Register (r/w) */
- struct {
- Bit8u wordlen_sel; /* 2-bit code for char length */
- bx_bool stopbits; /* select stop bit len */
- bx_bool parity_enable; /* ... */
- bx_bool evenparity_sel; /* ... */
- bx_bool stick_parity; /* ... */
- bx_bool break_cntl; /* 1=send break signal */
- bx_bool dlab; /* divisor latch access bit */
- } line_cntl;
- /* MODEM Control Register (r/w) */
- struct {
- bx_bool dtr; /* DTR output value */
- bx_bool rts; /* RTS output value */
- bx_bool out1; /* OUTPUT1 value */
- bx_bool out2; /* OUTPUT2 value */
- bx_bool local_loopback; /* 1=loopback mode */
- } modem_cntl;
- /* Line Status Register (r/w) */
- struct {
- bx_bool rxdata_ready; /* 1=receiver data ready */
- bx_bool overrun_error; /* 1=receive overrun detected */
- bx_bool parity_error; /* 1=rx char has a bad parity bit */
- bx_bool framing_error; /* 1=no stop bit detected for rx char */
- bx_bool break_int; /* 1=break signal detected */
- bx_bool thr_empty; /* 1=tx hold register (or fifo) is empty */
- bx_bool tsr_empty; /* 1=shift reg and hold reg empty */
- bx_bool fifo_error; /* 1=at least 1 err condition in fifo */
- } line_status;
- /* Modem Status Register (r/w) */
- struct {
- bx_bool delta_cts; /* 1=CTS changed since last read */
- bx_bool delta_dsr; /* 1=DSR changed since last read */
- bx_bool ri_trailedge; /* 1=RI moved from low->high */
- bx_bool delta_dcd; /* 1=CD changed since last read */
- bx_bool cts; /* CTS input value */
- bx_bool dsr; /* DSR input value */
- bx_bool ri; /* RI input value */
- bx_bool dcd; /* DCD input value */
- } modem_status;
-
- Bit8u scratch; /* Scratch Register (r/w) */
- Bit8u tsrbuffer; /* transmit shift register (internal) */
- Bit8u rx_fifo[16]; /* receive FIFO (internal) */
- Bit8u tx_fifo[16]; /* transmit FIFO (internal) */
- Bit8u divisor_lsb; /* Divisor latch, least-sig. byte */
- Bit8u divisor_msb; /* Divisor latch, most-sig. byte */
-} bx_serial_t;
-
-
-
-class bx_serial_c : public bx_devmodel_c {
-public:
- bx_serial_c(void);
- ~bx_serial_c(void);
- virtual void init(void);
- virtual void reset(unsigned type);
-#if USE_RAW_SERIAL
- serial_raw* raw;
-#endif // USE_RAW_SERIAL
-
-private:
- bx_serial_t s[BX_SERIAL_MAXDEV];
-
- static void lower_interrupt(Bit8u port);
- static void raise_interrupt(Bit8u port, int type);
-
- static void rx_fifo_enq(Bit8u port, Bit8u data);
-
- static void tx_timer_handler(void *);
- BX_SER_SMF void tx_timer(void);
-
- static void rx_timer_handler(void *);
- BX_SER_SMF void rx_timer(void);
-
- static void fifo_timer_handler(void *);
- BX_SER_SMF void fifo_timer(void);
-
- static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len);
- static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len);
-#if !BX_USE_SER_SMF
- Bit32u read(Bit32u address, unsigned io_len);
- void write(Bit32u address, Bit32u value, unsigned io_len);
-#endif
- };
-
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: serial_raw.h,v 1.2 2001/10/03 13:10:38 bdenney Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-#include <linux/serial.h>
-
-#define P_EVEN 0
-#define P_ODD 1
-#define C_BREAK 201
-
-class serial_raw : public logfunctions {
- public:
- serial_raw (char *ttypath, int signal);
- void set_baudrate (int rate);
- void set_data_bits (int );
- void set_stop_bits (int);
- void set_parity_mode (int, int);
- void transmit (int byte);
- void send_hangup ();
- int ready_transmit ();
- int ready_receive ();
- int receive ();
-};
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: slowdown_timer.cc,v 1.17.2.1 2004/02/06 22:14:36 danielg4 Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-//
-
-#include "bochs.h"
-#include <errno.h>
-
-//These need to stay printfs because they are useless in the log file.
-#define BX_SLOWDOWN_PRINTF_FEEDBACK 0
-
-#define SECINUSEC 1000000
-#define usectosec(a) ((a)/SECINUSEC)
-#define sectousec(a) ((a)*SECINUSEC)
-#define nsectousec(a) ((a)/1000)
-
-#define MSECINUSEC 1000
-#define usectomsec(a) ((a)/MSECINUSEC)
-
-#if BX_HAVE_USLEEP
-# define Qval 1000
-#else
-# define Qval SECINUSEC
-#endif
-
-#define MAXMULT 1.5
-#define REALTIME_Q SECINUSEC
-
-#define LOG_THIS bx_slowdown_timer.
-
-bx_slowdown_timer_c bx_slowdown_timer;
-
-bx_slowdown_timer_c::bx_slowdown_timer_c() {
- put("STIMER");
- settype(STIMERLOG);
-
-
- s.start_time=0;
- s.start_emulated_time=0;
- s.timer_handle=BX_NULL_TIMER_HANDLE;
-}
-
-void
-bx_slowdown_timer_c::init(void) {
-
- // Return early if slowdown timer not selected
- if ( (bx_options.clock.Osync->get () != BX_CLOCK_SYNC_SLOWDOWN)
- && (bx_options.clock.Osync->get () != BX_CLOCK_SYNC_BOTH) )
- return;
-
- BX_INFO(("using 'slowdown' timer synchronization method"));
- s.MAXmultiplier=MAXMULT;
- s.Q=Qval;
-
- if(s.MAXmultiplier<1)
- s.MAXmultiplier=1;
-
- s.start_time=sectousec(time(NULL));
- s.start_emulated_time = bx_pc_system.time_usec();
- s.lasttime=0;
- if (s.timer_handle == BX_NULL_TIMER_HANDLE) {
- s.timer_handle=bx_pc_system.register_timer(this, timer_handler, 100 , 1, 1,
- "slowdown_timer");
- }
- bx_pc_system.deactivate_timer(s.timer_handle);
- bx_pc_system.activate_timer(s.timer_handle,(Bit32u)s.Q,0);
-}
-
-void
-bx_slowdown_timer_c::reset(unsigned type)
-{
-}
-
-void
-bx_slowdown_timer_c::timer_handler(void * this_ptr) {
- bx_slowdown_timer_c * class_ptr = (bx_slowdown_timer_c *) this_ptr;
-
- class_ptr->handle_timer();
-}
-
-void
-bx_slowdown_timer_c::handle_timer() {
- Bit64u total_emu_time = (bx_pc_system.time_usec()) - s.start_emulated_time;
- Bit64u wanttime = s.lasttime+s.Q;
- Bit64u totaltime = sectousec(time(NULL)) - s.start_time;
- Bit64u thistime=(wanttime>totaltime)?wanttime:totaltime;
-
-#if BX_SLOWDOWN_PRINTF_FEEDBACK
- printf("Entering slowdown timer handler.\n");
-#endif
-
- /* Decide if we're behind.
- * Set interrupt interval accordingly. */
- if(totaltime > total_emu_time) {
- bx_pc_system.deactivate_timer(s.timer_handle);
- bx_pc_system.activate_timer(s.timer_handle,
- (Bit32u)(s.MAXmultiplier * (float)((Bit64s)s.Q)),
- 0);
-#if BX_SLOWDOWN_PRINTF_FEEDBACK
- printf("running at MAX speed\n");
-#endif
- } else {
- bx_pc_system.deactivate_timer(s.timer_handle);
- bx_pc_system.activate_timer(s.timer_handle,s.Q,0);
-#if BX_SLOWDOWN_PRINTF_FEEDBACK
- printf("running at NORMAL speed\n");
-#endif
- }
-
- /* Make sure we took at least one time quantum. */
- /* This is a little strange. I'll try to explain.
- * We're running bochs one second ahead of real time.
- * this gives us a very precise division on whether
- * we're ahead or behind the second line.
- * Basically, here's how it works:
- * *****|******************|***********...
- * Time Time+1sec
- * <^Bochs doesn't delay.
- * ^>Bochs delays.
- * <^Bochs runs at MAX speed.
- * ^>Bochs runs at normal
- */
- if(wanttime > (totaltime+REALTIME_Q)) {
-#if BX_HAVE_USLEEP
- usleep(s.Q);
-#elif BX_HAVE_MSLEEP
- msleep(usectomsec(s.Q));
-#elif BX_HAVE_SLEEP
- sleep(usectosec(s.Q));
-#else
-#error do not know have to sleep
-#endif //delay(wanttime-totaltime);
- /*alternatively: delay(Q);
- * This works okay because we share the delay between
- * two time quantums.
- */
-#if BX_SLOWDOWN_PRINTF_FEEDBACK
- printf("DELAYING for a quantum\n");
-#endif
- }
- s.lasttime=thistime;
-
- //Diagnostic info:
-#if 0
- if(wanttime > (totaltime+REALTIME_Q)) {
- if(totaltime > total_emu_time) {
- printf("Solving OpenBSD problem.\n");
- } else {
- printf("too fast.\n");
- }
- } else {
- if(totaltime > total_emu_time) {
- printf("too slow.\n");
- } else {
- printf("sometimes invalid state, normally okay.\n");
- }
- }
-#endif // Diagnostic info
-}
-
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: slowdown_timer.h,v 1.8 2003/08/19 00:10:38 cbothamy Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-
-class bx_slowdown_timer_c : public logfunctions {
-
-private:
- struct {
- Bit64u start_time;
- Bit64u start_emulated_time;
- Bit64u lasttime;
-
- int timer_handle;
-
- float MAXmultiplier;
- Bit64u Q; // (Q (in seconds))
- } s;
-
-public:
- bx_slowdown_timer_c();
-
- void init(void);
- void reset(unsigned type);
-
- static void timer_handler(void * this_ptr);
-
- void handle_timer();
-
-};
-
-extern bx_slowdown_timer_c bx_slowdown_timer;
-
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: soundlnx.cc,v 1.6 2002/12/24 10:12:26 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2001 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-// This file (SOUNDLNX.CC) written and donated by Josef Drexler
-
-
-#include "bochs.h"
-#if (defined(linux) || defined(__FreeBSD__)) && BX_SUPPORT_SB16
-#define LOG_THIS bx_sb16.
-
-#include <errno.h>
-#include <sys/ioctl.h>
-#include <sys/soundcard.h>
-
-bx_sound_linux_c::bx_sound_linux_c(bx_sb16_c *sb16)
- :bx_sound_output_c(sb16)
-{
- this->sb16 = sb16;
- midi = NULL;
- wavedevice = NULL;
- wave = -1;
-}
-
-bx_sound_linux_c::~bx_sound_linux_c()
-{
- // nothing for now
-}
-
-
-int bx_sound_linux_c::waveready()
-{
- return BX_SOUND_OUTPUT_OK;
-}
-
-int bx_sound_linux_c::midiready()
-{
- return BX_SOUND_OUTPUT_OK;
-}
-
-int bx_sound_linux_c::openmidioutput(char *device)
-{
- if ( (device == NULL) || (strlen(device) < 1) )
- return BX_SOUND_OUTPUT_ERR;
-
- midi = fopen(device,"w");
-
- if (midi == NULL)
- {
- WRITELOG( MIDILOG(2), "Couldn't open midi output device %s: %s.",
- device, strerror(errno));
- return BX_SOUND_OUTPUT_ERR;
- }
-
- return BX_SOUND_OUTPUT_OK;
-}
-
-
-int bx_sound_linux_c::sendmidicommand(int delta, int command, int length, Bit8u data[])
-{
- UNUSED(delta);
- // BX_PANIC(("Sendmidicommand!!");
-
- fputc(command, midi);
- fwrite(data, 1, length, midi);
- fflush(midi); // to start playing immediately
-
- return BX_SOUND_OUTPUT_OK;
-}
-
-
-int bx_sound_linux_c::closemidioutput()
-{
- fclose(midi);
-
- return BX_SOUND_OUTPUT_OK;
-}
-
-
-int bx_sound_linux_c::openwaveoutput(char *device)
-{
- int length = strlen(device) + 1;
-
- if (wavedevice != NULL)
- delete(wavedevice);
-
- wavedevice = new char[length];
-
- if (wavedevice == NULL)
- return BX_SOUND_OUTPUT_ERR;
-
- strncpy(wavedevice, device, length);
-
- return BX_SOUND_OUTPUT_OK;
-}
-
-int bx_sound_linux_c::startwaveplayback(int frequency, int bits, int stereo, int format)
-{
- int fmt, ret;
- int signeddata = format & 1;
-
- if ( (wavedevice == NULL) || (strlen(wavedevice) < 1) )
- return BX_SOUND_OUTPUT_ERR;
-
- if (wave == -1)
- wave = open(wavedevice, O_WRONLY);
- else
- if ( (frequency == oldfreq) &&
- (bits == oldbits) &&
- (stereo == oldstereo) &&
- (format == oldformat) )
- return BX_SOUND_OUTPUT_OK; // nothing to do
-
- oldfreq = frequency;
- oldbits = bits;
- oldstereo = stereo;
- oldformat = format;
-
- if (wave == -1)
- return BX_SOUND_OUTPUT_ERR;
-
- if (bits == 16)
- if (signeddata == 1)
- fmt = AFMT_S16_LE;
- else
- fmt = AFMT_U16_LE;
- else if (bits == 8)
- if (signeddata == 1)
- fmt = AFMT_S8;
- else
- fmt = AFMT_U8;
- else
- return BX_SOUND_OUTPUT_ERR;
-
- // set frequency etc.
- ret = ioctl(wave, SNDCTL_DSP_RESET);
- if (ret != 0)
- WRITELOG( WAVELOG(4), "ioctl(SNDCTL_DSP_RESET): %s", strerror(errno));
-
- /*
- ret = ioctl(wave, SNDCTL_DSP_SETFRAGMENT, &fragment);
- if (ret != 0)
- WRITELOG( WAVELOG(4), "ioctl(SNDCTL_DSP_SETFRAGMENT, %d): %s",
- fragment, strerror(errno));
- */
-
- ret = ioctl(wave, SNDCTL_DSP_SETFMT, &fmt);
- if (ret != 0) // abort if the format is unknown, to avoid playing noise
- {
- WRITELOG( WAVELOG(4), "ioctl(SNDCTL_DSP_SETFMT, %d): %s",
- fmt, strerror(errno));
- return BX_SOUND_OUTPUT_ERR;
- }
-
- ret = ioctl(wave, SNDCTL_DSP_STEREO, &stereo);
- if (ret != 0)
- WRITELOG( WAVELOG(4), "ioctl(SNDCTL_DSP_STEREO, %d): %s",
- stereo, strerror(errno));
-
- ret = ioctl(wave, SNDCTL_DSP_SPEED, &frequency);
- if (ret != 0)
- WRITELOG( WAVELOG(4), "ioctl(SNDCTL_DSP_SPEED, %d): %s",
- frequency, strerror(errno));
-
- // ioctl(wave, SNDCTL_DSP_GETBLKSIZE, &fragment);
- // WRITELOG( WAVELOG(4), "current output block size is %d", fragment);
-
- return BX_SOUND_OUTPUT_OK;
-}
-
-int bx_sound_linux_c::sendwavepacket(int length, Bit8u data[])
-{
- int ret;
-
- ret = write(wave, data, length);
-
- return BX_SOUND_OUTPUT_OK;
-}
-
-int bx_sound_linux_c::stopwaveplayback()
-{
- // ioctl(wave, SNDCTL_DSP_SYNC);
- // close(wave);
- // wave = -1;
-
- return BX_SOUND_OUTPUT_OK;
-}
-
-int bx_sound_linux_c::closewaveoutput()
-{
- if (wavedevice != NULL)
- delete(wavedevice);
-
- if (wave != -1)
- {
- close(wave);
- wave = -1;
- }
-
- wavedevice = NULL;
-
- return BX_SOUND_OUTPUT_OK;
-}
-
-#endif // defined(linux)
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: soundlnx.h,v 1.5 2002/12/24 10:12:26 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2001 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-// This file (SOUNDLNX.H) written and donated by Josef Drexler
-
-
-#if (defined(linux) || defined(__FreeBSD__))
-
-#include "bochs.h"
-
-#define BX_SOUND_LINUX_BUFSIZE BX_SOUND_OUTPUT_WAVEPACKETSIZE
-
-class bx_sound_linux_c : public bx_sound_output_c {
-public:
- bx_sound_linux_c(bx_sb16_c *sb16);
- BX_SOUND_VIRTUAL ~bx_sound_linux_c();
-
- // if virtual functions are used, we have to override them
- // and define our own. Otherwise this file will just implement
- // the original functions
-#ifdef BX_USE_SOUND_VIRTUAL
- BX_SOUND_VIRTUAL int waveready();
- BX_SOUND_VIRTUAL int midiready();
-
- BX_SOUND_VIRTUAL int openmidioutput(char *device);
- BX_SOUND_VIRTUAL int sendmidicommand(int delta, int command, int length, Bit8u data[]);
- BX_SOUND_VIRTUAL int closemidioutput();
-
- BX_SOUND_VIRTUAL int openwaveoutput(char *device);
- BX_SOUND_VIRTUAL int startwaveplayback(int frequency, int bits, int stereo, int format);
- BX_SOUND_VIRTUAL int sendwavepacket(int length, Bit8u data[]);
- BX_SOUND_VIRTUAL int stopwaveplayback();
- BX_SOUND_VIRTUAL int closewaveoutput();
-#endif
-
-private:
- bx_sb16_c *sb16;
- FILE *midi;
- char *wavedevice;
- int wave;
- int bufferpos;
- Bit8u audio_buffer[BX_SOUND_LINUX_BUFSIZE];
- int oldfreq,oldbits,oldstereo,oldformat;
-};
-
-#endif // defined(linux)
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: soundwin.cc,v 1.13 2003/04/05 08:26:49 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2001 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-// This file (SOUNDWIN.CC) written and donated by Josef Drexler
-
-// Define BX_PLUGGABLE in files that can be compiled into plugins. For
-// platforms that require a special tag on exported symbols, BX_PLUGGABLE
-// is used to know when we are exporting symbols and when we are importing.
-#define BX_PLUGGABLE
-
-#include "bochs.h"
-#if defined(WIN32) && BX_SUPPORT_SB16
-
-#define LOG_THIS bx_devices.pluginSB16Device->
-
-bx_sound_windows_c::bx_sound_windows_c(bx_sb16_c *sb16)
- :bx_sound_output_c(sb16)
-{
- this->sb16 = sb16;
-
- MidiOpen = 0;
- WaveOpen = 0;
-
- ismidiready = 1;
- iswaveready = 1;
-
- // size is the total size of the midi header and buffer and the
- // BX_SOUND_WINDOWS_NBUF wave header and buffers, all aligned
- // on a 16-byte boundary
-
-#define ALIGN(size) ( (size + 15) & ~15 )
-
-#define size ALIGN(sizeof(MIDIHDR)) \
- + ALIGN(sizeof(WAVEHDR)) \
- + ALIGN(BX_SOUND_WINDOWS_MAXSYSEXLEN) * BX_SOUND_WINDOWS_NBUF \
- + ALIGN(BX_SOUND_OUTPUT_WAVEPACKETSIZE) * BX_SOUND_WINDOWS_NBUF
-
- DataHandle = GlobalAlloc(GMEM_MOVEABLE | GMEM_SHARE, size);
- DataPointer = (Bit8u*) GlobalLock(DataHandle);
-
- if (DataPointer == NULL)
- BX_PANIC(("GlobalLock returned NULL-pointer"));
-
-#define NEWBUFFER(size) &(DataPointer[offset]); offset += ALIGN(size)
-
- int offset = 0;
- MidiHeader = (LPMIDIHDR) NEWBUFFER(sizeof(MIDIHDR));
- MidiData = (LPSTR) NEWBUFFER(BX_SOUND_WINDOWS_MAXSYSEXLEN);
-
- for (int bufnum=0; bufnum<BX_SOUND_WINDOWS_NBUF; bufnum++)
- {
- WaveHeader[bufnum] = (LPWAVEHDR) NEWBUFFER(sizeof(WAVEHDR));
- WaveData[bufnum] = (LPSTR) NEWBUFFER(BX_SOUND_OUTPUT_WAVEPACKETSIZE);
- }
-
- if (offset > size)
- BX_PANIC(("Allocated memory was too small!"));
-
-#undef size
-#undef ALIGN
-#undef NEWBUFFER
-}
-
-bx_sound_windows_c::~bx_sound_windows_c()
-{
- GlobalUnlock(DataHandle);
- GlobalFree(DataHandle);
-}
-
-int bx_sound_windows_c::waveready()
-{
- if (iswaveready == 0)
- checkwaveready();
-
- if (iswaveready == 1)
- return BX_SOUND_OUTPUT_OK;
- else
- return BX_SOUND_OUTPUT_ERR;
-}
-int bx_sound_windows_c::midiready()
-{
- if (ismidiready == 0)
- checkmidiready();
-
- if (ismidiready == 1)
- return BX_SOUND_OUTPUT_OK;
- else
- return BX_SOUND_OUTPUT_ERR;
-}
-
-int bx_sound_windows_c::openmidioutput(char *device)
-{
- // could make the output device selectable,
- // but currently only the midi mapper is supported
- UNUSED(device);
-
- UINT deviceid = (UINT) MIDIMAPPER;
-
- MidiOpen = 0;
-
- UINT ret = midiOutOpen( &MidiOut, deviceid, 0, 0, CALLBACK_NULL);
- if (ret == 0)
- MidiOpen = 1;
-
- WRITELOG( MIDILOG(4), "midiOutOpen() = %d, MidiOpen: %d", ret, MidiOpen);
-
- return (MidiOpen == 1) ? BX_SOUND_OUTPUT_OK : BX_SOUND_OUTPUT_ERR;
-}
-
-int bx_sound_windows_c::sendmidicommand(int delta, int command, int length, Bit8u data[])
-{
- UINT ret;
-
- if (MidiOpen != 1)
- return BX_SOUND_OUTPUT_ERR;
-
- if ( (command == 0xf0) || (command == 0xf7) || (length > 3) )
- {
- WRITELOG( WAVELOG(5), "SYSEX started, length %d", length);
- ismidiready = 0; // until the buffer is done
- memcpy(MidiData, data, length);
- MidiHeader->lpData = MidiData;
- MidiHeader->dwBufferLength = BX_SOUND_WINDOWS_MAXSYSEXLEN;
- MidiHeader->dwBytesRecorded = 0;
- MidiHeader->dwUser = 0;
- MidiHeader->dwFlags = 0;
- ret = midiOutPrepareHeader(MidiOut, MidiHeader, sizeof(*MidiHeader));
- if (ret != 0)
- WRITELOG( MIDILOG(2), "midiOutPrepareHeader() = %d", ret);
- ret = midiOutLongMsg(MidiOut, MidiHeader, sizeof(*MidiHeader));
- if (ret != 0)
- WRITELOG( MIDILOG(2), "midiOutLongMsg() = %d", ret);
- }
- else
- {
- DWORD msg = command;
-
- for (int i = 0; i<length; i++)
- msg |= (data[i] << (8 * (i + 1) ) );
-
- ret = midiOutShortMsg(MidiOut, msg);
- WRITELOG( MIDILOG(4), "midiOutShortMsg(%x) = %d", msg, ret);
- }
-
- return (ret == 0) ? BX_SOUND_OUTPUT_OK : BX_SOUND_OUTPUT_ERR;
-}
-
-int bx_sound_windows_c::closemidioutput()
-{
- UINT ret;
-
- if (MidiOpen != 1)
- return BX_SOUND_OUTPUT_ERR;
-
- ret = midiOutReset(MidiOut);
- if (ismidiready == 0)
- checkmidiready(); // to clear any pending SYSEX
-
- ret = midiOutClose(MidiOut);
- WRITELOG( MIDILOG(4), "midiOutClose() = %d", ret);
- MidiOpen = 0;
-
- return (ret == 0) ? BX_SOUND_OUTPUT_OK : BX_SOUND_OUTPUT_ERR;
-}
-
-int bx_sound_windows_c::openwaveoutput(char *device)
-{
- // could make the output device selectable,
- // but currently only the midi mapper is supported
- UNUSED(device);
-
- WRITELOG( WAVELOG(4), "openwaveoutput(%s)", device);
-
-#ifdef usewaveOut
- WaveDevice = (UINT) WAVEMAPPER;
-
- for (int i=0; i<BX_SOUND_WINDOWS_NBUF; i++)
- WaveHeader[i]->dwFlags = WHDR_DONE;
-
- head = 0;
- tailfull = 0;
- tailplay = 0;
- needreopen = 0;
-#endif
-
- return BX_SOUND_OUTPUT_OK;
-}
-
-int bx_sound_windows_c::playnextbuffer()
-{
- UINT ret;
- PCMWAVEFORMAT waveformat;
- int bufnum;
-
- // if the format is different, we have to reopen the device,
- // so reset it first
- if (needreopen != 0)
- if (WaveOpen != 0)
- ret = waveOutReset( WaveOut );
-
- // clean up the buffers and mark if output is ready
- checkwaveready();
-
- // do we have to play anything?
- if (tailplay == head)
- return BX_SOUND_OUTPUT_OK;
-
- // if the format is different, we have to close and reopen the device
- // or, just open the device if it's not open yet
- if ( (needreopen != 0) || (WaveOpen == 0) )
- {
- if (WaveOpen != 0)
- {
- ret = waveOutClose( WaveOut );
- WaveOpen = 0;
- }
-
- // try three times to find a suitable format
- for (int tries = 0; tries < 3; tries++)
- {
- int frequency = WaveInfo.frequency;
- int stereo = WaveInfo.stereo;
- int bits = WaveInfo.bits;
- int format = WaveInfo.format;
- int bps = (bits / 8) * (stereo + 1);
-
- waveformat.wf.wFormatTag = WAVE_FORMAT_PCM;
- waveformat.wf.nChannels = stereo + 1;
- waveformat.wf.nSamplesPerSec = frequency;
- waveformat.wf.nAvgBytesPerSec = frequency * bps;
- waveformat.wf.nBlockAlign = bps;
- waveformat.wBitsPerSample = bits;
-
- ret = waveOutOpen( &(WaveOut), WaveDevice, (LPWAVEFORMATEX)&(waveformat.wf), 0, 0, CALLBACK_NULL);
- if (ret != 0)
- {
- char errormsg[4*MAXERRORLENGTH+1];
- waveOutGetErrorTextA(ret, errormsg, 4*MAXERRORLENGTH+1);
- WRITELOG( WAVELOG(5), "waveOutOpen: %s", errormsg);
- switch (tries)
- {
- case 0: // maybe try a different frequency
- if (frequency < 15600)
- frequency = 11025;
- else if (frequency < 31200)
- frequency = 22050;
- else
- frequency = 44100;
-
- WRITELOG( WAVELOG(4), "Couldn't open wave device (error %d), trying frequency %d", ret, frequency);
-
- break;
- case 1: // or something else
- frequency = 11025;
- stereo = 0;
- bits = 8;
- bps = 1;
-
- WRITELOG( WAVELOG(4), "Couldn't open wave device again (error %d), trying 11KHz, mono, 8bit", ret);
-
- break;
- case 2: // nope, doesn't work
-
- WRITELOG( WAVELOG(2), "Couldn't open wave device (error %d)!", ret);
-
- return BX_SOUND_OUTPUT_ERR;
- }
- WRITELOG( WAVELOG(5), "The format was: wFormatTag=%d, nChannels=%d, nSamplesPerSec=%d,",
- waveformat.wf.wFormatTag, waveformat.wf.nChannels, waveformat.wf.nSamplesPerSec);
- WRITELOG( WAVELOG(5), " nAvgBytesPerSec=%d, nBlockAlign=%d, wBitsPerSample=%d",
- waveformat.wf.nAvgBytesPerSec, waveformat.wf.nBlockAlign, waveformat.wBitsPerSample);
-
- }
- else
- {
- WaveOpen = 1;
- needreopen = 0;
- break;
- }
- }
- }
-
- for (bufnum=tailplay; bufnum != head;
- bufnum++, bufnum &= BX_SOUND_WINDOWS_NMASK, tailplay=bufnum)
- {
- WRITELOG( WAVELOG(5), "Playing buffer %d", bufnum);
-
- // prepare the wave header
- WaveHeader[bufnum]->lpData = WaveData[bufnum];
- WaveHeader[bufnum]->dwBufferLength = length[bufnum];
- WaveHeader[bufnum]->dwBytesRecorded = length[bufnum];
- WaveHeader[bufnum]->dwUser = 0;
- WaveHeader[bufnum]->dwFlags = 0;
- WaveHeader[bufnum]->dwLoops = 1;
-
- ret = waveOutPrepareHeader(WaveOut, WaveHeader[bufnum], sizeof(*WaveHeader[bufnum]));
- if (ret != 0)
- {
- WRITELOG( WAVELOG(2), "waveOutPrepareHeader = %d", ret);
- return BX_SOUND_OUTPUT_ERR;
- }
-
- ret = waveOutWrite(WaveOut, WaveHeader[bufnum], sizeof(*WaveHeader[bufnum]));
- if (ret != 0)
- {
- char errormsg[4*MAXERRORLENGTH+1];
- waveOutGetErrorTextA(ret, errormsg, 4*MAXERRORLENGTH+1);
- WRITELOG( WAVELOG(5), "waveOutWrite: %s", errormsg);
- }
- }
- return BX_SOUND_OUTPUT_OK;
-}
-
-int bx_sound_windows_c::startwaveplayback(int frequency, int bits, int stereo, int format)
-{
- // UINT ret;
-
- WRITELOG( WAVELOG(4), "startwaveplayback(%d, %d, %d, %x)", frequency, bits, stereo, format);
-
-#ifdef usewaveOut
- // check if any of the properties have changed
- if ( (WaveInfo.frequency != frequency) ||
- (WaveInfo.bits != bits) ||
- (WaveInfo.stereo != stereo) ||
- (WaveInfo.format != format) )
- {
- needreopen = 1;
-
- // store the current settings to be used by sendwavepacket()
- WaveInfo.frequency = frequency;
- WaveInfo.bits = bits;
- WaveInfo.stereo = stereo;
- WaveInfo.format = format;
- }
-#endif
-
-#ifdef usesndPlaySnd
- int bps = (bits / 8) * (stereo + 1);
- LPWAVEFILEHEADER header = (LPWAVEFILEHEADER) WaveData;
-
- memcpy(header->RIFF, "RIFF", 4);
- memcpy(header->TYPE, "WAVE", 4);
- memcpy(header->chnk, "fmt ", 4);
- header->chnklen = 16;
- header->waveformat.wf.wFormatTag = WAVE_FORMAT_PCM;
- header->waveformat.wf.nChannels = stereo + 1;
- header->waveformat.wf.nSamplesPerSec = frequency;
- header->waveformat.wf.nAvgBytesPerSec = frequency * bps;
- header->waveformat.wf.nBlockAlign = bps;
- header->waveformat.wBitsPerSample = bits;
- memcpy(header->chnk2, "data", 4);
-#endif
-
- return BX_SOUND_OUTPUT_OK;
-}
-
-int bx_sound_windows_c::sendwavepacket(int length, Bit8u data[])
-{
-// UINT ret;
- int bufnum;
-
- WRITELOG( WAVELOG(4), "sendwavepacket(%d, %p)", length, data);
-
-#ifdef usewaveOut
- bufnum = head;
-
- memcpy(WaveData[bufnum], data, length);
- this->length[bufnum] = length;
-
- // select next buffer to write to
- bufnum++;
- bufnum &= BX_SOUND_WINDOWS_NMASK;
-
- if ( ( (bufnum + 1) & BX_SOUND_WINDOWS_NMASK) == tailfull )
- { // this should not actually happen!
- WRITELOG( WAVELOG(2), "Output buffer overflow! Not played. Iswaveready was %d", iswaveready);
- iswaveready = 0; // stop the output for a while
- return BX_SOUND_OUTPUT_ERR;
- }
-
- head = bufnum;
-
- // check if more buffers are available, otherwise stall the emulator
- if ( ( (bufnum + 2) & BX_SOUND_WINDOWS_NMASK) == tailfull )
- {
- WRITELOG( WAVELOG(5), "Buffer status: Head %d, TailFull %d, TailPlay %d. Stall.",
- head, tailfull, tailplay);
- iswaveready = 0;
- }
-
- playnextbuffer();
-
-#endif
-
-#ifdef usesndPlaySnd
- LPWAVEFILEHEADER header = (LPWAVEFILEHEADER) WaveData;
-
- header->length = length + 36;
- header->chnk2len = length;
-
- memcpy( &(header->data), data, length);
-
- FILE *test = fopen("test", "a");
- fwrite(WaveData, 1, length + 44, test);
- fclose(test);
-
- ret = sndPlaySoundA( (LPCSTR) header, SND_SYNC | SND_MEMORY );
- if (ret != 0)
- {
- WRITELOG( WAVELOG(3), "sndPlaySoundA: %d", ret);
- }
-#endif
-
- return BX_SOUND_OUTPUT_OK;
-}
-
-int bx_sound_windows_c::stopwaveplayback()
-{
- WRITELOG( WAVELOG(4), "stopwaveplayback()");
-
-#ifdef usewaveOut
- // this is handled by checkwaveready() when closing
-#endif
-
-#ifdef usesndPlaySnd
- sndPlaySoundA( NULL, SND_ASYNC | SND_MEMORY );
-
- WaveOpen = 0;
-#endif
-
- return BX_SOUND_OUTPUT_OK;
-}
-
-int bx_sound_windows_c::closewaveoutput()
-{
-// int bufnum;
-
- WRITELOG( WAVELOG(4), "closewaveoutput");
-
-#ifdef usewaveOut
- if (WaveOpen == 1)
- {
- waveOutReset(WaveOut);
-
- // let checkwaveready() clean up the buffers
- checkwaveready();
-
- waveOutClose(WaveOut);
-
- head = 0;
- tailfull = 0;
- tailplay = 0;
- needreopen = 0;
- }
-#endif
-
- return BX_SOUND_OUTPUT_OK;
-}
-
-void bx_sound_windows_c::checkmidiready()
-{
- UINT ret;
-
- if ( (MidiHeader->dwFlags & WHDR_DONE) != 0)
- {
- WRITELOG( MIDILOG(5), "SYSEX message done, midi ready again.");
- ret = midiOutUnprepareHeader( MidiOut, MidiHeader, sizeof(*MidiHeader));
- ismidiready = 1;
- }
-}
-void bx_sound_windows_c::checkwaveready()
-{
- int bufnum;
- UINT ret;
-
- // clean up all finished buffers and mark them as available
- for (bufnum=tailfull;
- (bufnum != tailplay) &&
- ( (WaveHeader[bufnum]->dwFlags & WHDR_DONE) != 0);
- bufnum++, bufnum &= BX_SOUND_WINDOWS_NMASK)
- {
- WRITELOG( WAVELOG(5), "Buffer %d done.", bufnum);
-
- ret = waveOutUnprepareHeader(WaveOut, WaveHeader[bufnum], sizeof(*WaveHeader[bufnum]));
- }
-
- tailfull = bufnum;
-
- // enable gathering data if a buffer is available
- if ( ( (head + 2) & BX_SOUND_WINDOWS_NMASK) != tailfull )
- {
- WRITELOG( WAVELOG(5), "Buffer status: Head %d, TailFull %d, TailPlay %d. Ready.",
- head, tailfull, tailplay);
- iswaveready = 1;
- }
-}
-
-#endif // defined(WIN32)
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: soundwin.h,v 1.3 2001/10/03 13:10:38 bdenney Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2001 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-// This file (SOUNDWIN.H) written and donated by Josef Drexler
-
-
-#if defined(WIN32)
-
-#include "bochs.h"
-#include <windows.h>
-
-// uncomment one of the following two #defines
-//#define usesndPlaySnd
-#define usewaveOut
-
-#define BX_SOUND_WINDOWS_MAXSYSEXLEN 256 // maximum supported length of a sysex message
-
-#define BX_SOUND_WINDOWS_NBUF 4 // number of buffers for the output, must be power of 2 and >= 4
-#define BX_SOUND_WINDOWS_NMASK (BX_SOUND_WINDOWS_NBUF - 1)
-
-#ifndef WAVEMAPPER
-#define WAVEMAPPER -1
-#endif
-
-// Definitions for WINMM.DLL, if not defined already
-#ifndef MMSYSERR_NOERROR
-
-#pragma pack(1)
-
-typedef UINT HMIDIOUT;
-typedef HMIDIOUT *LPHMIDIOUT;
-typedef struct midihdr_tag {
- LPSTR lpData;
- DWORD dwBufferLength;
- DWORD dwBytesRecorded;
- DWORD dwUser;
- DWORD dwFlags;
- struct midihdr_tag *lpNext;
- DWORD reserved;
-} MIDIHDR, *LPMIDIHDR;
-
-typedef UINT HWAVEOUT;
-typedef HWAVEOUT *LPHWAVEOUT;
-
-typedef struct wavehdr_tag {
- LPSTR lpData;
- DWORD dwBufferLength;
- DWORD dwBytesRecorded;
- DWORD dwUser;
- DWORD dwFlags;
- DWORD dwLoops;
- struct wavehdr_tag *lpNext;
- DWORD reserved;
-} WAVEHDR, *LPWAVEHDR;
-
-#define WHDR_DONE 0x00000001
-#define WHDR_PREPARED 0x00000002
-#define WHDR_BEGINLOOP 0x00000004
-#define WHDR_ENDLOOP 0x00000008
-#define WHDR_INQUEUE 0x00000010
-
-
-typedef struct waveformat_tag {
- WORD wFormatTag;
- WORD nChannels;
- DWORD nSamplesPerSec;
- DWORD nAvgBytesPerSec;
- WORD nBlockAlign;
-} WAVEFORMAT, *LPWAVEFORMAT;
-
-#define WAVE_FORMAT_PCM 1
-
-typedef struct pcmwaveformat_tag {
- WAVEFORMAT wf;
- WORD wBitsPerSample;
-} PCMWAVEFORMAT, *LPPCMWAVEFORMAT;
-
-#define MIDIMAPPER -1
-
-#define CALLBACK_NULL 0x00000000
-#define CALLBACK_WINDOW 0x00010000
-#define CALLBACK_TASK 0x00020000
-#define CALLBACK_FUNCTION 0x00030000
-
-#define MMSYSERR_NOERROR 0
-#define MMSYSERR_ERROR 1
-#define MMSYSERR_BADDEVICEID 2
-#define MMSYSERR_NOTENABLED 3
-#define MMSYSERR_ALLOCATED 4
-#define MMSYSERR_INVALHANDLE 5
-#define MMSYSERR_NODRIVER 6
-#define MMSYSERR_NOMEM 7
-#define MMSYSERR_NOTSUPPORTED 8
-#define MMSYSERR_NOMAP 7
-
-#define MIDIERR_UNPREPARED 64
-#define MIDIERR_STILLPLAYING 65
-#define MIDIERR_NOTREADY 66
-#define MIDIERR_NODEVICE 67
-
-#define WAVERR_BADFORMAT 32
-#define WAVERR_STILLPLAYING 33
-#define WAVERR_UNPREPARED 34
-#define WAVERR_SYNC 35
-
-#define MAXERRORLENGTH 128
-
-extern "C" {
-UINT STDCALL midiOutOpen(LPHMIDIOUT, UINT, DWORD, DWORD, DWORD);
-UINT STDCALL midiOutShortMsg(HMIDIOUT, DWORD);
-UINT STDCALL midiOutLongMsg(HMIDIOUT, LPMIDIHDR, UINT);
-UINT STDCALL midiOutPrepareHeader(HMIDIOUT, LPMIDIHDR, UINT);
-UINT STDCALL midiOutUnprepareHeader(HMIDIOUT, LPMIDIHDR, UINT);
-UINT STDCALL midiOutReset(HMIDIOUT);
-UINT STDCALL midiOutClose(HMIDIOUT);
-
-UINT STDCALL waveOutOpen(LPHWAVEOUT, UINT, LPWAVEFORMAT, DWORD, DWORD, DWORD);
-UINT STDCALL waveOutWrite(HWAVEOUT, LPWAVEHDR, UINT);
-UINT STDCALL waveOutPrepareHeader(HWAVEOUT, LPWAVEHDR, UINT);
-UINT STDCALL waveOutUnprepareHeader(HWAVEOUT, LPWAVEHDR, UINT);
-UINT STDCALL waveOutReset(HWAVEOUT);
-UINT STDCALL waveOutClose(HWAVEOUT);
-
-UINT STDCALL waveOutGetErrorTextA(UINT, LPSTR, UINT);
-
-BOOL STDCALL sndPlaySoundA(LPCSTR, UINT);
-}
-
-typedef struct {
- char RIFF[4];
- Bit32u length;
- char TYPE[4];
- char chnk[4];
- Bit32u chnklen;
- PCMWAVEFORMAT waveformat;
- char chnk2[4];
- Bit32u chnk2len;
- char data[1];
-} WAVEFILEHEADER, *LPWAVEFILEHEADER;
-#pragma pack(0)
-
-#endif // MMSYSERR_NOERROR defined
-
-class bx_sound_windows_c : public bx_sound_output_c {
-public:
- bx_sound_windows_c(bx_sb16_c *sb16);
- BX_SOUND_VIRTUAL ~bx_sound_windows_c();
-
- // if virtual functions are used, we have to override them
- // and define our own. Otherwise this file will just implement
- // the original functions
-#ifdef BX_USE_SOUND_VIRTUAL
- BX_SOUND_VIRTUAL int waveready();
- BX_SOUND_VIRTUAL int midiready();
-
- BX_SOUND_VIRTUAL int openmidioutput(char *device);
- BX_SOUND_VIRTUAL int sendmidicommand(int delta, int command, int length, Bit8u data[]);
- BX_SOUND_VIRTUAL int closemidioutput();
-
- BX_SOUND_VIRTUAL int openwaveoutput(char *device);
- BX_SOUND_VIRTUAL int startwaveplayback(int frequency, int bits, int stereo, int format);
- BX_SOUND_VIRTUAL int sendwavepacket(int length, Bit8u data[]);
- BX_SOUND_VIRTUAL int stopwaveplayback();
- BX_SOUND_VIRTUAL int closewaveoutput();
-#endif
-
-private:
- bx_sb16_c *sb16;
-
- struct bx_sb16_waveinfo_struct {
- int frequency;
- int bits;
- int stereo;
- int format;
- };
-
- HMIDIOUT MidiOut; // Midi output device
- int MidiOpen; // is it open?
- HWAVEOUT WaveOut; // Wave output device
- int WaveOpen; // is it open?
-
- UINT WaveDevice; // Wave device ID, for waveOutOpen
-
- // some data for the wave buffers
- HANDLE DataHandle; // returned by GlobalAlloc()
- Bit8u *DataPointer; // returned by GlobalLock()
-
- LPWAVEHDR WaveHeader[BX_SOUND_WINDOWS_NBUF];
- LPSTR WaveData[BX_SOUND_WINDOWS_NBUF];
- int length[BX_SOUND_WINDOWS_NBUF]; // length of the data in the buffer
- int needreopen; // if the format has changed
- int head,tailfull,tailplay; // These are for three states of the buffers: empty, full, played
- bx_sb16_waveinfo_struct WaveInfo; // format for the next buffer to be played
- int iswaveready;
-
- // and the midi buffer for the SYSEX messages
- LPMIDIHDR MidiHeader;
- LPSTR MidiData;
- int ismidiready;
-
- int playnextbuffer();
- void checkmidiready();
- void checkwaveready();
-};
-
-#endif // defined(WIN32)
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: state_file.cc,v 1.9 2001/12/21 19:33:18 bdenney Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2001 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-
-// Classes for helping to make checkpoints of the emulator state.
-
-
-
-#include "bochs.h"
-#define LOG_THIS log->
-
-
-
-FILE *state_file::get_handle()
-{
- BX_INFO(("state_file::get_handle()"));
- return NULL;
-}
-
-void state_file::write(Bit8u)
-{
- BX_PANIC(("state_file::write(Bit8u)"));
-}
-
-void state_file::write(Bit16u)
-{
- BX_PANIC(("state_file::write(Bit16u)"));
-}
-
-void state_file::write(Bit32u)
-{
- BX_PANIC(("state_file::write(Bit32u)"));
-}
-
-void state_file::write(Bit64u)
-{
- BX_PANIC(("state_file::write(Bit64u)"));
-}
-
-void state_file::write(const void *, size_t)
-{
- BX_PANIC(("state_file::write(const void *, size_t)"));
-}
-
-void state_file::read(Bit8u &)
-{
- BX_PANIC(("state_file::read(uint8 &)"));
-}
-
-void state_file::read(Bit16u &)
-{
- BX_PANIC(("state_file::read(uint16 &)"));
-}
-
-void state_file::read(Bit32u &)
-{
- BX_PANIC(("state_file::read(uint32 &)"));
-}
-
-void state_file::read(Bit64u &)
-{
- BX_PANIC(("state_file::read(uint64 &)"));
-}
-
-void state_file::read(void *, size_t)
-{
- BX_PANIC(("state_file::read(void *, size_t)"));
-}
-
-void state_file::write_check(const char *)
-{
- BX_PANIC(("state_file::write_check()"));
-}
-
-void state_file::read_check (const char *)
-{
- BX_PANIC(("state_file::read_check()"));
-}
-
-void
-state_file::init(void)
-{
- log = new class logfunctions();
- log->put("STAT");
- log->settype(GENLOG);
-}
-
-
-state_file::state_file (const char *name, const char *options)
-{
- UNUSED(name);
- UNUSED(options);
- init();
- BX_DEBUG(( "Init(const char *, const char *)." ));
-}
-
-state_file::state_file (FILE *f)
-{
- UNUSED(f);
- init();
- BX_INFO(("Init(FILE *)."));
-}
-
-state_file::~state_file()
-{
- BX_DEBUG(("Exit."));
- if ( log != NULL )
- {
- delete log;
- log = NULL;
- }
-}
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: unmapped.cc,v 1.22 2003/08/10 17:19:49 akrisak Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2001 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-
-// Define BX_PLUGGABLE in files that can be compiled into plugins. For
-// platforms that require a special tag on exported symbols, BX_PLUGGABLE
-// is used to know when we are exporting symbols and when we are importing.
-#define BX_PLUGGABLE
-
-#include "bochs.h"
-
-#define LOG_THIS theUnmappedDevice->
-
-
-bx_unmapped_c *theUnmappedDevice = NULL;
-
- int
-libunmapped_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[])
-{
- theUnmappedDevice = new bx_unmapped_c ();
- bx_devices.pluginUnmapped = theUnmappedDevice;
- BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theUnmappedDevice, BX_PLUGIN_UNMAPPED);
- return(0); // Success
-}
-
- void
-libunmapped_LTX_plugin_fini(void)
-{
-}
-
-bx_unmapped_c::bx_unmapped_c(void)
-{
- put("UNMP");
- settype(UNMAPLOG);
- s.port80 = 0x00;
- s.port8e = 0x00;
- s.shutdown = 0;
-}
-
-bx_unmapped_c::~bx_unmapped_c(void)
-{
- // Nothing yet
-}
-
- void
-bx_unmapped_c::init(void)
-{
- DEV_register_default_ioread_handler(this, read_handler, "Unmapped", 7);
- DEV_register_default_iowrite_handler(this, write_handler, "Unmapped", 7);
-}
-
- void
-bx_unmapped_c::reset(unsigned type)
-{
-}
-
- // static IO port read callback handler
- // redirects to non-static class handler to avoid virtual functions
-
- Bit32u
-bx_unmapped_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len)
-{
-#if !BX_USE_UM_SMF
- bx_unmapped_c *class_ptr = (bx_unmapped_c *) this_ptr;
-
- return( class_ptr->read(address, io_len) );
-}
-
- Bit32u
-bx_unmapped_c::read(Bit32u address, unsigned io_len)
-{
-#else
- UNUSED(this_ptr);
-#endif // !BX_USE_UM_SMF
- UNUSED(io_len);
-
- Bit32u retval;
-
- // This function gets called for access to any IO ports which
- // are not mapped to any device handler. Reads return 0
-
- if (address >= 0x02e0 && address <= 0x02ef) {
- retval = 0;
- goto return_from_read;
- }
-
- switch (address) {
- case 0x80:
- retval = BX_UM_THIS s.port80;
- break;
- case 0x8e:
- retval = BX_UM_THIS s.port8e;
- break;
-#if BX_PORT_E9_HACK
- // Unused port on ISA - this can be used by the emulated code
- // to detect it is running inside Bochs and that the debugging
- // features are available (write 0xFF or something on unused
- // port 0x80, then read from 0xe9, if value is 0xe9, debug
- // output is available) (see write() for that) -- Andreas and Emmanuel
- case 0xe9:
- retval = 0xe9;
- break;
-#endif
- case 0x03df:
- retval = 0xffffffff;
- BX_DEBUG(("unsupported IO read from port %04x (CGA)", address));
- break;
- case 0x023a:
- case 0x02f8: /* UART */
- case 0x02f9: /* UART */
- case 0x02fb: /* UART */
- case 0x02fc: /* UART */
- case 0x02fd: /* UART */
- case 0x02ea:
- case 0x02eb:
- case 0x03e8:
- case 0x03e9:
- case 0x03ea:
- case 0x03eb:
- case 0x03ec:
- case 0x03ed:
- case 0x03f8: /* UART */
- case 0x03f9: /* UART */
- case 0x03fb: /* UART */
- case 0x03fc: /* UART */
- case 0x03fd: /* UART */
- case 0x17c6:
- retval = 0xffffffff;
- BX_DEBUG(("unsupported IO read from port %04x", address));
- break;
- default:
- retval = 0xffffffff;
- }
-
- return_from_read:
- if (bx_dbg.unsupported_io)
- switch (io_len) {
- case 1:
- retval = (Bit8u)retval;
- BX_DEBUG(("unmapped: 8-bit read from %04x = %02x", address, retval));
- break;
- case 2:
- retval = (Bit16u)retval;
- BX_DEBUG(("unmapped: 16-bit read from %04x = %04x", address, retval));
- break;
- case 4:
- BX_DEBUG(("unmapped: 32-bit read from %04x = %08x", address, retval));
- break;
- default:
- BX_DEBUG(("unmapped: %d-bit read from %04x = %x", io_len * 8, address, retval));
- }
- return retval;
-}
-
-
- // static IO port write callback handler
- // redirects to non-static class handler to avoid virtual functions
-
- void
-bx_unmapped_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len)
-{
-#if !BX_USE_UM_SMF
- bx_unmapped_c *class_ptr = (bx_unmapped_c *) this_ptr;
-
- class_ptr->write(address, value, io_len);
-}
-
- void
-bx_unmapped_c::write(Bit32u address, Bit32u value, unsigned io_len)
-{
-#else
- UNUSED(this_ptr);
-#endif // !BX_USE_UM_SMF
- UNUSED(io_len);
-
-
- // This function gets called for access to any IO ports which
- // are not mapped to any device handler. Writes to an unmapped
- // IO port are ignored.
-
-// ???
-
- if (address >= 0x02e0 && address <= 0x02ef)
- goto return_from_write;
-
- switch (address) {
- case 0x80: // diagnostic test port to display progress of POST
- //BX_DEBUG(("Diagnostic port 80h: write = %02xh", (unsigned) value));
- BX_UM_THIS s.port80 = value;
- break;
-
- case 0x8e: // ???
- BX_UM_THIS s.port8e = value;
- break;
-
-#if BX_PORT_E9_HACK
- // This port doesn't exist on normal ISA architecture. However,
- // we define a convention here, to display on the console of the
- // system running Bochs, anything that is written to it. The
- // idea is to provide debug output very early when writing
- // BIOS or OS code for example, without having to bother with
- // properly setting up a serial port or anything.
- //
- // Idea by Andreas Beck (andreas.beck@ggi-project.org)
-
- case 0xe9:
- putchar(value);
- fflush(stdout);
- break;
-#endif
-
- case 0xed: // Dummy port used as I/O delay
- break;
- case 0xee: // ???
- break;
-
- case 0x2f2:
- case 0x2f3:
- case 0x2f4:
- case 0x2f5:
- case 0x2f6:
- case 0x2f7:
- case 0x3e8:
- case 0x3e9:
- case 0x3eb:
- case 0x3ec:
- case 0x3ed:
- // BX_DEBUG(("unsupported IO write to port %04x of %02x",
- // address, value));
- break;
-
- case 0x8900: // Shutdown port, could be moved in a PM device
- // or a host <-> guest communication device
- switch (value) {
- case 'S': if (BX_UM_THIS s.shutdown == 0) BX_UM_THIS s.shutdown = 1; break;
- case 'h': if (BX_UM_THIS s.shutdown == 1) BX_UM_THIS s.shutdown = 2; break;
- case 'u': if (BX_UM_THIS s.shutdown == 2) BX_UM_THIS s.shutdown = 3; break;
- case 't': if (BX_UM_THIS s.shutdown == 3) BX_UM_THIS s.shutdown = 4; break;
- case 'd': if (BX_UM_THIS s.shutdown == 4) BX_UM_THIS s.shutdown = 5; break;
- case 'o': if (BX_UM_THIS s.shutdown == 5) BX_UM_THIS s.shutdown = 6; break;
- case 'w': if (BX_UM_THIS s.shutdown == 6) BX_UM_THIS s.shutdown = 7; break;
- case 'n': if (BX_UM_THIS s.shutdown == 7) BX_UM_THIS s.shutdown = 8; break;
-#if BX_DEBUGGER
- // Very handy for debugging:
- // output 'D' to port 8900, and bochs quits to debugger
- case 'D': bx_debug_break (); break;
-#endif
- default : BX_UM_THIS s.shutdown = 0; break;
- }
- if (BX_UM_THIS s.shutdown == 8) {
- bx_user_quit = 1;
- LOG_THIS setonoff(LOGLEV_PANIC, ACT_FATAL);
- BX_PANIC(("Shutdown port: shutdown requested"));
- }
- break;
-
- case 0xfedc:
- bx_dbg.debugger = (value > 0);
- BX_DEBUG(( "DEBUGGER = %u", (unsigned) bx_dbg.debugger));
- break;
-
- default:
- break;
- }
- return_from_write:
- if (bx_dbg.unsupported_io)
- switch (io_len) {
- case 1:
- BX_INFO(("unmapped: 8-bit write to %04x = %02x", address, value));
- break;
- case 2:
- BX_INFO(("unmapped: 16-bit write to %04x = %04x", address, value));
- break;
- case 4:
- BX_INFO(("unmapped: 32-bit write to %04x = %08x", address, value));
- break;
- default:
- BX_INFO(("unmapped: %d-bit write to %04x = %x", io_len * 8, address, value));
- break;
- }
-}
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: unmapped.h,v 1.10 2002/10/24 21:07:52 bdenney Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2001 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-
-
-#if BX_USE_UM_SMF
-# define BX_UM_SMF static
-# define BX_UM_THIS theUnmappedDevice->
-#else
-# define BX_UM_SMF
-# define BX_UM_THIS this->
-#endif
-
-
-
-class bx_unmapped_c : public bx_devmodel_c {
-public:
- bx_unmapped_c(void);
- ~bx_unmapped_c(void);
-
- virtual void init(void);
- virtual void reset (unsigned type);
-
-private:
-
- static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len);
- static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len);
-#if !BX_USE_UM_SMF
- Bit32u read(Bit32u address, unsigned io_len);
- void write(Bit32u address, Bit32u value, unsigned io_len);
-#endif
-
-
- struct {
- Bit8u port80;
- Bit8u port8e;
- Bit8u shutdown;
- } s; // state information
-
- };
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: vga.cc,v 1.94.2.1 2004/02/02 22:37:48 cbothamy Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-// Define BX_PLUGGABLE in files that can be compiled into plugins. For
-// platforms that require a special tag on exported symbols, BX_PLUGGABLE
-// is used to know when we are exporting symbols and when we are importing.
-#define BX_PLUGGABLE
-
-#include "bochs.h"
-
-#define LOG_THIS theVga->
-
-/* NOTES:
- * I take it data rotate is a true rotate with carry of bit 0 to bit 7.
- * support map mask (3c5 reg 02)
- */
-
-/* Notes from cb
- *
- * It seems that the vga card should support multi bytes IO reads and write
- * From my tests, inw(port) return port+1 * 256 + port, except for port 0x3c9
- * (PEL data register, data cycling). More reverse engineering is needed.
- * This would fix the gentoo bug.
- */
-
-// (mch)
-#define VGA_TRACE_FEATURE
-
-// Only reference the array if the tile numbers are within the bounds
-// of the array. If out of bounds, do nothing.
-#define SET_TILE_UPDATED(xtile,ytile,value) \
- do { \
- if (((xtile) < BX_NUM_X_TILES) && ((ytile) < BX_NUM_Y_TILES)) \
- BX_VGA_THIS s.vga_tile_updated[(xtile)][(ytile)] = value; \
- } while (0)
-
-// Only reference the array if the tile numbers are within the bounds
-// of the array. If out of bounds, return 0.
-#define GET_TILE_UPDATED(xtile,ytile) \
- ((((xtile) < BX_NUM_X_TILES) && ((ytile) < BX_NUM_Y_TILES))? \
- BX_VGA_THIS s.vga_tile_updated[(xtile)][(ytile)] \
- : 0)
-
-static const Bit8u ccdat[16][4] = {
- { 0x00, 0x00, 0x00, 0x00 },
- { 0xff, 0x00, 0x00, 0x00 },
- { 0x00, 0xff, 0x00, 0x00 },
- { 0xff, 0xff, 0x00, 0x00 },
- { 0x00, 0x00, 0xff, 0x00 },
- { 0xff, 0x00, 0xff, 0x00 },
- { 0x00, 0xff, 0xff, 0x00 },
- { 0xff, 0xff, 0xff, 0x00 },
- { 0x00, 0x00, 0x00, 0xff },
- { 0xff, 0x00, 0x00, 0xff },
- { 0x00, 0xff, 0x00, 0xff },
- { 0xff, 0xff, 0x00, 0xff },
- { 0x00, 0x00, 0xff, 0xff },
- { 0xff, 0x00, 0xff, 0xff },
- { 0x00, 0xff, 0xff, 0xff },
- { 0xff, 0xff, 0xff, 0xff },
-};
-
-bx_vga_c *theVga = NULL;
-
-unsigned old_iHeight = 0, old_iWidth = 0, old_MSL = 0, old_BPP = 0;
-
- int
-libvga_LTX_plugin_init(plugin_t *plugin, plugintype_t type, int argc, char *argv[])
-{
- theVga = new bx_vga_c ();
- bx_devices.pluginVgaDevice = theVga;
- BX_REGISTER_DEVICE_DEVMODEL(plugin, type, theVga, BX_PLUGIN_VGA);
- return(0); // Success
-}
-
- void
-libvga_LTX_plugin_fini(void)
-{
-}
-
-bx_vga_c::bx_vga_c(void)
-{
- put("VGA");
- s.vga_mem_updated = 0;
- s.x_tilesize = X_TILESIZE;
- s.y_tilesize = Y_TILESIZE;
- timer_id = BX_NULL_TIMER_HANDLE;
-}
-
-
-bx_vga_c::~bx_vga_c(void)
-{
- // nothing for now
-}
-
-
- void
-bx_vga_c::init(void)
-{
- unsigned i;
- unsigned x,y;
-
- unsigned addr;
- for (addr=0x03B4; addr<=0x03B5; addr++) {
- DEV_register_ioread_handler(this, read_handler, addr, "vga video", 1);
- DEV_register_iowrite_handler(this, write_handler, addr, "vga video", 3);
- }
-
- for (addr=0x03BA; addr<=0x03BA; addr++) {
- DEV_register_ioread_handler(this, read_handler, addr, "vga video", 1);
- DEV_register_iowrite_handler(this, write_handler, addr, "vga video", 3);
- }
-
- for (addr=0x03C0; addr<=0x03CF; addr++) {
- DEV_register_ioread_handler(this, read_handler, addr, "vga video", 1);
- DEV_register_iowrite_handler(this, write_handler, addr, "vga video", 3);
- }
-
- for (addr=0x03D4; addr<=0x03D5; addr++) {
- DEV_register_ioread_handler(this, read_handler, addr, "vga video", 1);
- DEV_register_iowrite_handler(this, write_handler, addr, "vga video", 3);
- }
-
- for (addr=0x03DA; addr<=0x03DA; addr++) {
- DEV_register_ioread_handler(this, read_handler, addr, "vga video", 1);
- DEV_register_iowrite_handler(this, write_handler, addr, "vga video", 3);
- }
-
-
- BX_VGA_THIS s.misc_output.color_emulation = 1;
- BX_VGA_THIS s.misc_output.enable_ram = 1;
- BX_VGA_THIS s.misc_output.clock_select = 0;
- BX_VGA_THIS s.misc_output.select_high_bank = 0;
- BX_VGA_THIS s.misc_output.horiz_sync_pol = 1;
- BX_VGA_THIS s.misc_output.vert_sync_pol = 1;
-
- BX_VGA_THIS s.attribute_ctrl.mode_ctrl.graphics_alpha = 0;
- BX_VGA_THIS s.attribute_ctrl.mode_ctrl.display_type = 0;
- BX_VGA_THIS s.attribute_ctrl.mode_ctrl.enable_line_graphics = 1;
- BX_VGA_THIS s.attribute_ctrl.mode_ctrl.blink_intensity = 0;
- BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_panning_compat = 0;
- BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_clock_select = 0;
- BX_VGA_THIS s.attribute_ctrl.mode_ctrl.internal_palette_size = 0;
-
- BX_VGA_THIS s.line_offset=80;
- BX_VGA_THIS s.line_compare=1023;
- BX_VGA_THIS s.vertical_display_end=399;
-
- for (i=0; i<=0x18; i++)
- BX_VGA_THIS s.CRTC.reg[i] = 0;
- BX_VGA_THIS s.CRTC.address = 0;
-
- BX_VGA_THIS s.attribute_ctrl.flip_flop = 0;
- BX_VGA_THIS s.attribute_ctrl.address = 0;
- BX_VGA_THIS s.attribute_ctrl.video_enabled = 1;
- for (i=0; i<16; i++)
- BX_VGA_THIS s.attribute_ctrl.palette_reg[i] = 0;
- BX_VGA_THIS s.attribute_ctrl.overscan_color = 0;
- BX_VGA_THIS s.attribute_ctrl.color_plane_enable = 0x0f;
- BX_VGA_THIS s.attribute_ctrl.horiz_pel_panning = 0;
- BX_VGA_THIS s.attribute_ctrl.color_select = 0;
-
- for (i=0; i<256; i++) {
- BX_VGA_THIS s.pel.data[i].red = 0;
- BX_VGA_THIS s.pel.data[i].green = 0;
- BX_VGA_THIS s.pel.data[i].blue = 0;
- }
- BX_VGA_THIS s.pel.write_data_register = 0;
- BX_VGA_THIS s.pel.write_data_cycle = 0;
- BX_VGA_THIS s.pel.read_data_register = 0;
- BX_VGA_THIS s.pel.read_data_cycle = 0;
- BX_VGA_THIS s.pel.dac_state = 0x01;
- BX_VGA_THIS s.pel.mask = 0xff;
-
- BX_VGA_THIS s.graphics_ctrl.index = 0;
- BX_VGA_THIS s.graphics_ctrl.set_reset = 0;
- BX_VGA_THIS s.graphics_ctrl.enable_set_reset = 0;
- BX_VGA_THIS s.graphics_ctrl.color_compare = 0;
- BX_VGA_THIS s.graphics_ctrl.data_rotate = 0;
- BX_VGA_THIS s.graphics_ctrl.raster_op = 0;
- BX_VGA_THIS s.graphics_ctrl.read_map_select = 0;
- BX_VGA_THIS s.graphics_ctrl.write_mode = 0;
- BX_VGA_THIS s.graphics_ctrl.read_mode = 0;
- BX_VGA_THIS s.graphics_ctrl.odd_even = 0;
- BX_VGA_THIS s.graphics_ctrl.chain_odd_even = 0;
- BX_VGA_THIS s.graphics_ctrl.shift_reg = 0;
- BX_VGA_THIS s.graphics_ctrl.graphics_alpha = 0;
- BX_VGA_THIS s.graphics_ctrl.memory_mapping = 2; // monochrome text mode
- BX_VGA_THIS s.graphics_ctrl.color_dont_care = 0;
- BX_VGA_THIS s.graphics_ctrl.bitmask = 0;
- for (i=0; i<4; i++) {
- BX_VGA_THIS s.graphics_ctrl.latch[i] = 0;
- }
-
- BX_VGA_THIS s.sequencer.index = 0;
- BX_VGA_THIS s.sequencer.map_mask = 0;
- for (i=0; i<4; i++) {
- BX_VGA_THIS s.sequencer.map_mask_bit[i] = 0;
- }
- BX_VGA_THIS s.sequencer.reset1 = 1;
- BX_VGA_THIS s.sequencer.reset2 = 1;
- BX_VGA_THIS s.sequencer.reg1 = 0;
- BX_VGA_THIS s.sequencer.char_map_select = 0;
- BX_VGA_THIS s.sequencer.extended_mem = 1; // display mem greater than 64K
- BX_VGA_THIS s.sequencer.odd_even = 1; // use sequential addressing mode
- BX_VGA_THIS s.sequencer.chain_four = 0; // use map mask & read map select
-
- memset(BX_VGA_THIS s.vga_memory, 0, sizeof(BX_VGA_THIS s.vga_memory));
-
- BX_VGA_THIS s.vga_mem_updated = 0;
- for (y=0; y<480/Y_TILESIZE; y++)
- for (x=0; x<640/X_TILESIZE; x++)
- SET_TILE_UPDATED (x, y, 0);
-
- {
- /* ??? should redo this to pass X args */
- char *argv[1] = { "bochs" };
- bx_gui->init(1, &argv[0], BX_VGA_THIS s.x_tilesize, BX_VGA_THIS s.y_tilesize);
- }
-
- BX_INFO(("interval=%u", bx_options.Ovga_update_interval->get ()));
- if (BX_VGA_THIS timer_id == BX_NULL_TIMER_HANDLE) {
- BX_VGA_THIS timer_id = bx_pc_system.register_timer(this, timer_handler,
- bx_options.Ovga_update_interval->get (), 1, 1, "vga");
- }
-
- /* video card with BIOS ROM */
- DEV_cmos_set_reg(0x14, (DEV_cmos_get_reg(0x14) & 0xcf) | 0x00);
-
- BX_VGA_THIS s.charmap_address = 0;
- BX_VGA_THIS s.x_dotclockdiv2 = 0;
- BX_VGA_THIS s.y_doublescan = 0;
-
-#if BX_SUPPORT_VBE
- // The following is for the vbe display extension
-
- for (addr=VBE_DISPI_IOPORT_INDEX; addr<=VBE_DISPI_IOPORT_DATA; addr++) {
- DEV_register_ioread_handler(this, vbe_read_handler, addr, "vga video", 7);
- DEV_register_iowrite_handler(this, vbe_write_handler, addr, "vga video", 7);
- }
-#if !BX_PCI_USB_SUPPORT
- for (addr=VBE_DISPI_IOPORT_INDEX_OLD; addr<=VBE_DISPI_IOPORT_DATA_OLD; addr++) {
- DEV_register_ioread_handler(this, vbe_read_handler, addr, "vga video", 7);
- DEV_register_iowrite_handler(this, vbe_write_handler, addr, "vga video", 7);
- }
-#endif
- BX_VGA_THIS s.vbe_cur_dispi=VBE_DISPI_ID0;
- BX_VGA_THIS s.vbe_xres=640;
- BX_VGA_THIS s.vbe_yres=480;
- BX_VGA_THIS s.vbe_bpp=8;
- BX_VGA_THIS s.vbe_bank=0;
- BX_VGA_THIS s.vbe_enabled=0;
- BX_VGA_THIS s.vbe_curindex=0;
- BX_VGA_THIS s.vbe_offset_x=0;
- BX_VGA_THIS s.vbe_offset_y=0;
- BX_VGA_THIS s.vbe_virtual_xres=640;
- BX_VGA_THIS s.vbe_virtual_yres=480;
- BX_VGA_THIS s.vbe_bpp_multiplier=1;
- BX_VGA_THIS s.vbe_virtual_start=0;
- BX_VGA_THIS s.vbe_line_byte_width=640;
- BX_VGA_THIS s.vbe_lfb_enabled=0;
-
-
- BX_INFO(("VBE Bochs Display Extension Enabled"));
-#endif
- bios_init();
-}
-
- void
-bx_vga_c::bios_init()
-{
- int i;
-
- BX_VGA_THIS s.misc_output.color_emulation = 1;
- BX_VGA_THIS s.misc_output.enable_ram = 1;
- BX_VGA_THIS s.misc_output.clock_select = 1;
- BX_VGA_THIS s.misc_output.select_high_bank = 1;
- BX_VGA_THIS s.misc_output.horiz_sync_pol = 1;
- BX_VGA_THIS s.misc_output.vert_sync_pol = 0;
- BX_VGA_THIS s.CRTC.address = 15;
- BX_VGA_THIS s.CRTC.reg[0] = 95;
- BX_VGA_THIS s.CRTC.reg[1] = 79;
- BX_VGA_THIS s.CRTC.reg[2] = 80;
- BX_VGA_THIS s.CRTC.reg[3] = 130;
- BX_VGA_THIS s.CRTC.reg[4] = 85;
- BX_VGA_THIS s.CRTC.reg[5] = 129;
- BX_VGA_THIS s.CRTC.reg[6] = 191;
- BX_VGA_THIS s.CRTC.reg[7] = 31;
- BX_VGA_THIS s.CRTC.reg[8] = 0;
- BX_VGA_THIS s.CRTC.reg[9] = 79;
- BX_VGA_THIS s.CRTC.reg[10] = 14;
- BX_VGA_THIS s.CRTC.reg[11] = 15;
- BX_VGA_THIS s.CRTC.reg[12] = 0;
- BX_VGA_THIS s.CRTC.reg[13] = 0;
- BX_VGA_THIS s.CRTC.reg[14] = 5;
- BX_VGA_THIS s.CRTC.reg[15] = 160;
- BX_VGA_THIS s.CRTC.reg[16] = 156;
- BX_VGA_THIS s.CRTC.reg[17] = 142;
- BX_VGA_THIS s.CRTC.reg[18] = 143;
- BX_VGA_THIS s.CRTC.reg[19] = 40;
- BX_VGA_THIS s.CRTC.reg[20] = 31;
- BX_VGA_THIS s.CRTC.reg[21] = 150;
- BX_VGA_THIS s.CRTC.reg[22] = 185;
- BX_VGA_THIS s.CRTC.reg[23] = 163;
- BX_VGA_THIS s.CRTC.reg[24] = 255;
- BX_VGA_THIS s.attribute_ctrl.flip_flop = 1;
- BX_VGA_THIS s.attribute_ctrl.address = 0;
- BX_VGA_THIS s.attribute_ctrl.video_enabled = 1;
- BX_VGA_THIS s.attribute_ctrl.palette_reg[0] = 0;
- BX_VGA_THIS s.attribute_ctrl.palette_reg[1] = 1;
- BX_VGA_THIS s.attribute_ctrl.palette_reg[2] = 2;
- BX_VGA_THIS s.attribute_ctrl.palette_reg[3] = 3;
- BX_VGA_THIS s.attribute_ctrl.palette_reg[4] = 4;
- BX_VGA_THIS s.attribute_ctrl.palette_reg[5] = 5;
- BX_VGA_THIS s.attribute_ctrl.palette_reg[6] = 6;
- BX_VGA_THIS s.attribute_ctrl.palette_reg[7] = 7;
- BX_VGA_THIS s.attribute_ctrl.palette_reg[8] = 8;
- BX_VGA_THIS s.attribute_ctrl.palette_reg[9] = 9;
- BX_VGA_THIS s.attribute_ctrl.palette_reg[10] = 10;
- BX_VGA_THIS s.attribute_ctrl.palette_reg[11] = 11;
- BX_VGA_THIS s.attribute_ctrl.palette_reg[12] = 12;
- BX_VGA_THIS s.attribute_ctrl.palette_reg[13] = 13;
- BX_VGA_THIS s.attribute_ctrl.palette_reg[14] = 14;
- BX_VGA_THIS s.attribute_ctrl.palette_reg[15] = 15;
- BX_VGA_THIS s.attribute_ctrl.overscan_color = 0;
- BX_VGA_THIS s.attribute_ctrl.color_plane_enable = 15;
- BX_VGA_THIS s.attribute_ctrl.horiz_pel_panning = 8;
- BX_VGA_THIS s.attribute_ctrl.color_select = 0;
- BX_VGA_THIS s.attribute_ctrl.mode_ctrl.graphics_alpha = 0;
- BX_VGA_THIS s.attribute_ctrl.mode_ctrl.display_type = 0;
- BX_VGA_THIS s.attribute_ctrl.mode_ctrl.enable_line_graphics = 1;
- BX_VGA_THIS s.attribute_ctrl.mode_ctrl.blink_intensity = 1;
- BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_panning_compat = 0;
- BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_clock_select = 0;
- BX_VGA_THIS s.attribute_ctrl.mode_ctrl.internal_palette_size = 0;
- BX_VGA_THIS s.pel.write_data_register = 16;
- BX_VGA_THIS s.pel.write_data_cycle = 0;
- BX_VGA_THIS s.pel.read_data_register = 0;
- BX_VGA_THIS s.pel.read_data_cycle = 0;
- BX_VGA_THIS s.pel.dac_state = 0;
- memset((BX_VGA_THIS s.pel.data), 0, 256);
- BX_VGA_THIS s.pel.data[0].red = 0;
- BX_VGA_THIS s.pel.data[0].green = 0;
- BX_VGA_THIS s.pel.data[0].blue = 0;
- BX_VGA_THIS s.pel.mask = 255;
- BX_VGA_THIS s.graphics_ctrl.index = 6;
- BX_VGA_THIS s.graphics_ctrl.set_reset = 0;
- BX_VGA_THIS s.graphics_ctrl.enable_set_reset = 0;
- BX_VGA_THIS s.graphics_ctrl.color_compare = 0;
- BX_VGA_THIS s.graphics_ctrl.data_rotate = 0;
- BX_VGA_THIS s.graphics_ctrl.raster_op = 0;
- BX_VGA_THIS s.graphics_ctrl.read_map_select = 0;
- BX_VGA_THIS s.graphics_ctrl.write_mode = 0;
- BX_VGA_THIS s.graphics_ctrl.read_mode = 0;
- BX_VGA_THIS s.graphics_ctrl.odd_even = 1;
- BX_VGA_THIS s.graphics_ctrl.chain_odd_even = 1;
- BX_VGA_THIS s.graphics_ctrl.shift_reg = 0;
- BX_VGA_THIS s.graphics_ctrl.graphics_alpha = 0;
- BX_VGA_THIS s.graphics_ctrl.memory_mapping = 3;
- BX_VGA_THIS s.graphics_ctrl.color_dont_care = 15;
- BX_VGA_THIS s.graphics_ctrl.bitmask = 255;
- BX_VGA_THIS s.graphics_ctrl.latch[0] = 0;
- BX_VGA_THIS s.graphics_ctrl.latch[1] = 0;
- BX_VGA_THIS s.graphics_ctrl.latch[2] = 0;
- BX_VGA_THIS s.graphics_ctrl.latch[3] = 0;
- BX_VGA_THIS s.sequencer.index = 3;
- BX_VGA_THIS s.sequencer.map_mask = 3;
- BX_VGA_THIS s.sequencer.map_mask_bit[0] = 1;
- BX_VGA_THIS s.sequencer.map_mask_bit[1] = 1;
- BX_VGA_THIS s.sequencer.map_mask_bit[2] = 0;
- BX_VGA_THIS s.sequencer.map_mask_bit[3] = 0;
- BX_VGA_THIS s.sequencer.reset1 = 1;
- BX_VGA_THIS s.sequencer.reset2 = 1;
- BX_VGA_THIS s.sequencer.reg1 = 0;
- BX_VGA_THIS s.sequencer.char_map_select = 0;
- BX_VGA_THIS s.sequencer.extended_mem = 1;
- BX_VGA_THIS s.sequencer.odd_even = 0;
- BX_VGA_THIS s.sequencer.chain_four = 0;
- BX_VGA_THIS s.vga_mem_updated = 1;
- BX_VGA_THIS s.x_tilesize = 16;
- BX_VGA_THIS s.y_tilesize = 24;
- BX_VGA_THIS s.line_offset = 160;
- BX_VGA_THIS s.line_compare = 1023;
- BX_VGA_THIS s.vertical_display_end = 399;
- memset((BX_VGA_THIS s.vga_tile_updated), 0, BX_NUM_X_TILES * BX_NUM_Y_TILES);
-
- memset((BX_VGA_THIS s.vga_memory), ' ', 256 * 1024);
- for(i = 0; i < 256 * 1024;i+=2) {
- BX_VGA_THIS s.vga_memory[i] = ' ';
- BX_VGA_THIS s.vga_memory[i+1] = 0x07;
-
- }
- memset((BX_VGA_THIS s.text_snapshot), 0, 32 * 1024);
- memset((BX_VGA_THIS s.rgb), 0, 3 * 256);
- memset((BX_VGA_THIS s.tile), 0, X_TILESIZE * Y_TILESIZE * 4);
- BX_VGA_THIS s.charmap_address = 0;
- BX_VGA_THIS s.x_dotclockdiv2 = 0;
- BX_VGA_THIS s.y_doublescan = 1;
-}
-
- void
-bx_vga_c::reset(unsigned type)
-{
-}
-
-
- void
-bx_vga_c::determine_screen_dimensions(unsigned *piHeight, unsigned *piWidth)
-{
- int ai[0x20];
- int i,h,v;
- for ( i = 0 ; i < 0x20 ; i++ )
- ai[i] = BX_VGA_THIS s.CRTC.reg[i];
-
- h = (ai[1] + 1) * 8;
- v = (ai[18] | ((ai[7] & 0x02) << 7) | ((ai[7] & 0x40) << 3)) + 1;
-
- if ( BX_VGA_THIS s.graphics_ctrl.shift_reg == 0 )
- {
- *piWidth = 640;
- *piHeight = 480;
-
- if ( BX_VGA_THIS s.CRTC.reg[6] == 0xBF )
- {
- if (BX_VGA_THIS s.CRTC.reg[23] == 0xA3 &&
- BX_VGA_THIS s.CRTC.reg[20] == 0x40 &&
- BX_VGA_THIS s.CRTC.reg[9] == 0x41)
- {
- *piWidth = 320;
- *piHeight = 240;
- }
- else {
- if (BX_VGA_THIS s.x_dotclockdiv2) h <<= 1;
- *piWidth = h;
- *piHeight = v;
- }
- }
- else if ((h >= 640) && (v >= 480)) {
- *piWidth = h;
- *piHeight = v;
- }
- }
- else if ( BX_VGA_THIS s.graphics_ctrl.shift_reg == 2 )
- {
-
- if ( BX_VGA_THIS s.sequencer.chain_four )
- {
- *piWidth = h;
- *piHeight = v;
- }
- else
- {
- *piWidth = h;
- *piHeight = v;
- }
- }
- else
- {
- if (BX_VGA_THIS s.x_dotclockdiv2) h <<= 1;
- *piWidth = h;
- *piHeight = v;
- }
-}
-
-
- // static IO port read callback handler
- // redirects to non-static class handler to avoid virtual functions
-
- Bit32u
-bx_vga_c::read_handler(void *this_ptr, Bit32u address, unsigned io_len)
-{
-#if !BX_USE_VGA_SMF
- bx_vga_c *class_ptr = (bx_vga_c *) this_ptr;
-
- return( class_ptr->read(address, io_len) );
-}
-
-
- Bit32u
-bx_vga_c::read(Bit32u address, unsigned io_len)
-{
-#else
- UNUSED(this_ptr);
-#endif // !BX_USE_VGA_SMF
- bx_bool horiz_retrace = 0, vert_retrace = 0;
- Bit64u usec;
- Bit16u vertres;
- Bit8u retval;
-
-#if defined(VGA_TRACE_FEATURE)
- Bit32u ret = 0;
-#define RETURN(x) do { ret = (x); goto read_return; } while (0)
-#else
-#define RETURN return
-#endif
-
-#ifdef __OS2__
- if ( bx_options.videomode == BX_VIDEO_DIRECT )
- {
- return _inp(address);
- }
-#endif
-
-#if !defined(VGA_TRACE_FEATURE)
- BX_DEBUG(("io read from 0x%04x", (unsigned) address));
-#endif
-
- if ( (address >= 0x03b0) && (address <= 0x03bf) &&
- (BX_VGA_THIS s.misc_output.color_emulation) ) {
- RETURN(0xff);
- }
- if ( (address >= 0x03d0) && (address <= 0x03df) &&
- (BX_VGA_THIS s.misc_output.color_emulation==0) ) {
- RETURN(0xff);
- }
-
- switch (address) {
- case 0x03ba: /* Input Status 1 (monochrome emulation modes) */
- case 0x03ca: /* Feature Control ??? */
- case 0x03da: /* Input Status 1 (color emulation modes) */
- // bit3: Vertical Retrace
- // 0 = display is in the display mode
- // 1 = display is in the vertical retrace mode
- // bit0: Display Enable
- // 0 = display is in the display mode
- // 1 = display is not in the display mode; either the
- // horizontal or vertical retrace period is active
-
- // using 72 Hz vertical frequency
- usec = bx_pc_system.time_usec();
- switch ( ( BX_VGA_THIS s.misc_output.vert_sync_pol << 1) | BX_VGA_THIS s.misc_output.horiz_sync_pol )
- {
- case 0: vertres = 200; break;
- case 1: vertres = 400; break;
- case 2: vertres = 350; break;
- default: vertres = 480; break;
- }
- if ((usec % 13888) < 70) {
- vert_retrace = 1;
- }
- if ((usec % (13888 / vertres)) == 0) {
- horiz_retrace = 1;
- }
-
- retval = 0;
- if (horiz_retrace || vert_retrace)
- retval = 0x01;
- if (vert_retrace)
- retval |= 0x08;
-
- /* reading this port resets the flip-flop to address mode */
- BX_VGA_THIS s.attribute_ctrl.flip_flop = 0;
- RETURN(retval);
- break;
-
-
- case 0x03c0: /* */
- if (BX_VGA_THIS s.attribute_ctrl.flip_flop == 0) {
- //BX_INFO(("io read: 0x3c0: flip_flop = 0"));
- retval =
- (BX_VGA_THIS s.attribute_ctrl.video_enabled << 5) |
- BX_VGA_THIS s.attribute_ctrl.address;
- RETURN(retval);
- }
- else {
- BX_ERROR(("io read: 0x3c0: flip_flop != 0"));
- return(0);
- }
- break;
-
- case 0x03c1: /* */
- switch (BX_VGA_THIS s.attribute_ctrl.address) {
- case 0x00: case 0x01: case 0x02: case 0x03:
- case 0x04: case 0x05: case 0x06: case 0x07:
- case 0x08: case 0x09: case 0x0a: case 0x0b:
- case 0x0c: case 0x0d: case 0x0e: case 0x0f:
- retval = BX_VGA_THIS s.attribute_ctrl.palette_reg[BX_VGA_THIS s.attribute_ctrl.address];
- RETURN(retval);
- break;
- case 0x10: /* mode control register */
- retval =
- (BX_VGA_THIS s.attribute_ctrl.mode_ctrl.graphics_alpha << 0) |
- (BX_VGA_THIS s.attribute_ctrl.mode_ctrl.display_type << 1) |
- (BX_VGA_THIS s.attribute_ctrl.mode_ctrl.enable_line_graphics << 2) |
- (BX_VGA_THIS s.attribute_ctrl.mode_ctrl.blink_intensity << 3) |
- (BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_panning_compat << 5) |
- (BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_clock_select << 6) |
- (BX_VGA_THIS s.attribute_ctrl.mode_ctrl.internal_palette_size << 7);
- RETURN(retval);
- break;
- case 0x11: /* overscan color register */
- RETURN(BX_VGA_THIS s.attribute_ctrl.overscan_color);
- break;
- case 0x12: /* color plane enable */
- RETURN(BX_VGA_THIS s.attribute_ctrl.color_plane_enable);
- break;
- case 0x13: /* horizontal PEL panning register */
- RETURN(BX_VGA_THIS s.attribute_ctrl.horiz_pel_panning);
- break;
- case 0x14: /* color select register */
- RETURN(BX_VGA_THIS s.attribute_ctrl.color_select);
- break;
- default:
- BX_INFO(("io read: 0x3c1: unknown register 0x%02x",
- (unsigned) BX_VGA_THIS s.attribute_ctrl.address));
- RETURN(0);
- }
- break;
-
- case 0x03c2: /* Input Status 0 */
- BX_DEBUG(("io read 0x3c2: input status #0: ignoring"));
- RETURN(0);
- break;
-
- case 0x03c3: /* VGA Enable Register */
- RETURN(1);
- break;
-
- case 0x03c4: /* Sequencer Index Register */
- RETURN(BX_VGA_THIS s.sequencer.index);
- break;
-
- case 0x03c5: /* Sequencer Registers 00..04 */
- switch (BX_VGA_THIS s.sequencer.index) {
- case 0: /* sequencer: reset */
- BX_DEBUG(("io read 0x3c5: sequencer reset"));
- RETURN(BX_VGA_THIS s.sequencer.reset1 | (BX_VGA_THIS s.sequencer.reset2<<1));
- break;
- case 1: /* sequencer: clocking mode */
- BX_DEBUG(("io read 0x3c5: sequencer clocking mode"));
- RETURN(BX_VGA_THIS s.sequencer.reg1);
- break;
- case 2: /* sequencer: map mask register */
- RETURN(BX_VGA_THIS s.sequencer.map_mask);
- break;
- case 3: /* sequencer: character map select register */
- RETURN(BX_VGA_THIS s.sequencer.char_map_select);
- break;
- case 4: /* sequencer: memory mode register */
- retval =
- (BX_VGA_THIS s.sequencer.extended_mem << 1) |
- (BX_VGA_THIS s.sequencer.odd_even << 2) |
- (BX_VGA_THIS s.sequencer.chain_four << 3);
- RETURN(retval);
- break;
-
- default:
- BX_DEBUG(("io read 0x3c5: index %u unhandled",
- (unsigned) BX_VGA_THIS s.sequencer.index));
- RETURN(0);
- }
- break;
-
- case 0x03c6: /* PEL mask ??? */
- RETURN(BX_VGA_THIS s.pel.mask);
- break;
-
- case 0x03c7: /* DAC state, read = 11b, write = 00b */
- RETURN(BX_VGA_THIS s.pel.dac_state);
- break;
-
- case 0x03c8: /* PEL address write mode */
- RETURN(BX_VGA_THIS s.pel.write_data_register);
- break;
-
- case 0x03c9: /* PEL Data Register, colors 00..FF */
- if (BX_VGA_THIS s.pel.dac_state == 0x03) {
- switch (BX_VGA_THIS s.pel.read_data_cycle) {
- case 0:
- retval = BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.read_data_register].red;
- break;
- case 1:
- retval = BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.read_data_register].green;
- break;
- case 2:
- retval = BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.read_data_register].blue;
- break;
- default:
- retval = 0; // keep compiler happy
- }
- BX_VGA_THIS s.pel.read_data_cycle++;
- if (BX_VGA_THIS s.pel.read_data_cycle >= 3) {
- BX_VGA_THIS s.pel.read_data_cycle = 0;
- BX_VGA_THIS s.pel.read_data_register++;
- }
- }
- else {
- retval = 0x3f;
- }
- RETURN(retval);
- break;
-
- case 0x03cc: /* Miscellaneous Output / Graphics 1 Position ??? */
- retval =
- ((BX_VGA_THIS s.misc_output.color_emulation & 0x01) << 0) |
- ((BX_VGA_THIS s.misc_output.enable_ram & 0x01) << 1) |
- ((BX_VGA_THIS s.misc_output.clock_select & 0x03) << 2) |
- ((BX_VGA_THIS s.misc_output.select_high_bank & 0x01) << 5) |
- ((BX_VGA_THIS s.misc_output.horiz_sync_pol & 0x01) << 6) |
- ((BX_VGA_THIS s.misc_output.vert_sync_pol & 0x01) << 7);
- RETURN(retval);
- break;
-
- case 0x03ce: /* Graphics Controller Index Register */
- RETURN(BX_VGA_THIS s.graphics_ctrl.index);
- break;
-
- case 0x03cd: /* ??? */
- BX_DEBUG(("io read from 03cd"));
- RETURN(0x00);
- break;
-
- case 0x03cf: /* Graphics Controller Registers 00..08 */
- switch (BX_VGA_THIS s.graphics_ctrl.index) {
- case 0: /* Set/Reset */
- RETURN(BX_VGA_THIS s.graphics_ctrl.set_reset);
- break;
- case 1: /* Enable Set/Reset */
- RETURN(BX_VGA_THIS s.graphics_ctrl.enable_set_reset);
- break;
- case 2: /* Color Compare */
- RETURN(BX_VGA_THIS s.graphics_ctrl.color_compare);
- break;
- case 3: /* Data Rotate */
- retval =
- ((BX_VGA_THIS s.graphics_ctrl.raster_op & 0x03) << 3) |
- ((BX_VGA_THIS s.graphics_ctrl.data_rotate & 0x07) << 0);
- RETURN(retval);
- break;
- case 4: /* Read Map Select */
- RETURN(BX_VGA_THIS s.graphics_ctrl.read_map_select);
- break;
- case 5: /* Mode */
- retval =
- ((BX_VGA_THIS s.graphics_ctrl.shift_reg & 0x03) << 5) |
- ((BX_VGA_THIS s.graphics_ctrl.odd_even & 0x01 ) << 4) |
- ((BX_VGA_THIS s.graphics_ctrl.read_mode & 0x01) << 3) |
- ((BX_VGA_THIS s.graphics_ctrl.write_mode & 0x03) << 0);
-
- if (BX_VGA_THIS s.graphics_ctrl.odd_even ||
- BX_VGA_THIS s.graphics_ctrl.shift_reg)
- BX_DEBUG(("io read 0x3cf: reg 05 = 0x%02x", (unsigned) retval));
- RETURN(retval);
- break;
- case 6: /* Miscellaneous */
- retval =
- ((BX_VGA_THIS s.graphics_ctrl.memory_mapping & 0x03 ) << 2) |
- ((BX_VGA_THIS s.graphics_ctrl.odd_even & 0x01) << 1) |
- ((BX_VGA_THIS s.graphics_ctrl.graphics_alpha & 0x01) << 0);
- RETURN(retval);
- break;
- case 7: /* Color Don't Care */
- RETURN(BX_VGA_THIS s.graphics_ctrl.color_dont_care);
- break;
- case 8: /* Bit Mask */
- RETURN(BX_VGA_THIS s.graphics_ctrl.bitmask);
- break;
- default:
- /* ??? */
- BX_DEBUG(("io read: 0x3cf: index %u unhandled",
- (unsigned) BX_VGA_THIS s.graphics_ctrl.index));
- RETURN(0);
- }
- break;
-
- case 0x03d4: /* CRTC Index Register (color emulation modes) */
- RETURN(BX_VGA_THIS s.CRTC.address);
- break;
-
- case 0x03b5: /* CRTC Registers (monochrome emulation modes) */
- case 0x03d5: /* CRTC Registers (color emulation modes) */
- if (BX_VGA_THIS s.CRTC.address > 0x18) {
- BX_DEBUG(("io read: invalid CRTC register 0x%02x",
- (unsigned) BX_VGA_THIS s.CRTC.address));
- RETURN(0);
- }
- RETURN(BX_VGA_THIS s.CRTC.reg[BX_VGA_THIS s.CRTC.address]);
- break;
-
- case 0x03b4: /* CRTC Index Register (monochrome emulation modes) */
- case 0x03cb: /* not sure but OpenBSD reads it a lot */
- default:
- BX_INFO(("io read from vga port 0x%02x", (unsigned) address));
- RETURN(0); /* keep compiler happy */
- }
-
-#if defined(VGA_TRACE_FEATURE)
- read_return:
- BX_DEBUG(("8-bit read from %04x = %02x", (unsigned) address, ret));
- return ret;
-#endif
-}
-#if defined(VGA_TRACE_FEATURE)
-#undef RETURN
-#endif
-
- // static IO port write callback handler
- // redirects to non-static class handler to avoid virtual functions
-
- void
-bx_vga_c::write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len)
-{
-#if !BX_USE_VGA_SMF
- bx_vga_c *class_ptr = (bx_vga_c *) this_ptr;
-
- class_ptr->write(address, value, io_len, 0);
-#else
- UNUSED(this_ptr);
- theVga->write(address, value, io_len, 0);
-#endif
-}
-
- void
-bx_vga_c::write_handler_no_log(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len)
-{
-#if !BX_USE_VGA_SMF
- bx_vga_c *class_ptr = (bx_vga_c *) this_ptr;
-
- class_ptr->write(address, value, io_len, 1);
-#else
- UNUSED(this_ptr);
- theVga->write(address, value, io_len, 1);
-#endif
-}
-
- void
-bx_vga_c::write(Bit32u address, Bit32u value, unsigned io_len, bx_bool no_log)
-{
- unsigned i;
- Bit8u charmap1, charmap2, prev_memory_mapping;
- bx_bool prev_video_enabled, prev_line_graphics, prev_int_pal_size;
- bx_bool prev_graphics_alpha, prev_chain_odd_even;
- bx_bool needs_update = 0;
-
-#if defined(VGA_TRACE_FEATURE)
- if (!no_log)
- switch (io_len) {
- case 1:
- BX_DEBUG(("8-bit write to %04x = %02x", (unsigned)address, (unsigned)value));
- break;
- case 2:
- BX_DEBUG(("16-bit write to %04x = %04x", (unsigned)address, (unsigned)value));
- break;
- default:
- BX_PANIC(("Weird VGA write size"));
- }
-#else
- if (io_len == 1) {
- BX_DEBUG(("io write to 0x%04x = 0x%02x", (unsigned) address,
- (unsigned) value));
- }
-#endif
-
- if (io_len == 2) {
-#if BX_USE_VGA_SMF
- bx_vga_c::write_handler_no_log(0, address, value & 0xff, 1);
- bx_vga_c::write_handler_no_log(0, address+1, (value >> 8) & 0xff, 1);
-#else
- bx_vga_c::write(address, value & 0xff, 1, 1);
- bx_vga_c::write(address+1, (value >> 8) & 0xff, 1, 1);
-#endif
- return;
- }
-
-#ifdef __OS2__
- if ( bx_options.videomode == BX_VIDEO_DIRECT )
- {
- _outp(address,value);
- return;
- }
-#endif
-
- if ( (address >= 0x03b0) && (address <= 0x03bf) &&
- (BX_VGA_THIS s.misc_output.color_emulation) )
- return;
- if ( (address >= 0x03d0) && (address <= 0x03df) &&
- (BX_VGA_THIS s.misc_output.color_emulation==0) )
- return;
-
- switch (address) {
- case 0x03ba: /* Feature Control (monochrome emulation modes) */
-#if !defined(VGA_TRACE_FEATURE)
- BX_DEBUG(("io write 3ba: feature control: ignoring"));
-#endif
- break;
-
- case 0x03c0: /* Attribute Controller */
- if (BX_VGA_THIS s.attribute_ctrl.flip_flop == 0) { /* address mode */
- prev_video_enabled = BX_VGA_THIS s.attribute_ctrl.video_enabled;
- BX_VGA_THIS s.attribute_ctrl.video_enabled = (value >> 5) & 0x01;
-#if !defined(VGA_TRACE_FEATURE)
- BX_DEBUG(("io write 3c0: video_enabled = %u",
- (unsigned) BX_VGA_THIS s.attribute_ctrl.video_enabled));
-#endif
- if (BX_VGA_THIS s.attribute_ctrl.video_enabled == 0)
- bx_gui->clear_screen();
- else if (!prev_video_enabled) {
-#if !defined(VGA_TRACE_FEATURE)
- BX_DEBUG(("found enable transition"));
-#endif
- needs_update = 1;
- }
- value &= 0x1f; /* address = bits 0..4 */
- BX_VGA_THIS s.attribute_ctrl.address = value;
- switch (value) {
- case 0x00: case 0x01: case 0x02: case 0x03:
- case 0x04: case 0x05: case 0x06: case 0x07:
- case 0x08: case 0x09: case 0x0a: case 0x0b:
- case 0x0c: case 0x0d: case 0x0e: case 0x0f:
- break;
-
- default:
- BX_DEBUG(("io write 3c0: address mode reg=%u",
- (unsigned) value));
- }
- }
- else { /* data-write mode */
- switch (BX_VGA_THIS s.attribute_ctrl.address) {
- case 0x00: case 0x01: case 0x02: case 0x03:
- case 0x04: case 0x05: case 0x06: case 0x07:
- case 0x08: case 0x09: case 0x0a: case 0x0b:
- case 0x0c: case 0x0d: case 0x0e: case 0x0f:
- if (value != BX_VGA_THIS s.attribute_ctrl.palette_reg[BX_VGA_THIS s.attribute_ctrl.address]) {
- BX_VGA_THIS s.attribute_ctrl.palette_reg[BX_VGA_THIS s.attribute_ctrl.address] =
- value;
- needs_update = 1;
- }
- break;
- case 0x10: // mode control register
- prev_line_graphics = BX_VGA_THIS s.attribute_ctrl.mode_ctrl.enable_line_graphics;
- prev_int_pal_size = BX_VGA_THIS s.attribute_ctrl.mode_ctrl.internal_palette_size;
- BX_VGA_THIS s.attribute_ctrl.mode_ctrl.graphics_alpha =
- (value >> 0) & 0x01;
- BX_VGA_THIS s.attribute_ctrl.mode_ctrl.display_type =
- (value >> 1) & 0x01;
- BX_VGA_THIS s.attribute_ctrl.mode_ctrl.enable_line_graphics =
- (value >> 2) & 0x01;
- BX_VGA_THIS s.attribute_ctrl.mode_ctrl.blink_intensity =
- (value >> 3) & 0x01;
- BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_panning_compat =
- (value >> 5) & 0x01;
- BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_clock_select =
- (value >> 6) & 0x01;
- BX_VGA_THIS s.attribute_ctrl.mode_ctrl.internal_palette_size =
- (value >> 7) & 0x01;
- if (((value >> 2) & 0x01) != prev_line_graphics) {
- bx_gui->set_text_charmap(
- & BX_VGA_THIS s.vga_memory[0x20000 + BX_VGA_THIS s.charmap_address]);
- BX_VGA_THIS s.vga_mem_updated = 1;
- }
- if (((value >> 7) & 0x01) != prev_int_pal_size) {
- needs_update = 1;
- }
-#if !defined(VGA_TRACE_FEATURE)
- BX_DEBUG(("io write 3c0: mode control: %02x h",
- (unsigned) value));
-#endif
- break;
- case 0x11: // Overscan Color Register
- BX_VGA_THIS s.attribute_ctrl.overscan_color = (value & 0x3f);
-#if !defined(VGA_TRACE_FEATURE)
- BX_DEBUG(("io write 3c0: overscan color = %02x",
- (unsigned) value));
-#endif
- break;
- case 0x12: // Color Plane Enable Register
- BX_VGA_THIS s.attribute_ctrl.color_plane_enable = (value & 0x0f);
- needs_update = 1;
-#if !defined(VGA_TRACE_FEATURE)
- BX_DEBUG(("io write 3c0: color plane enable = %02x",
- (unsigned) value));
-#endif
- break;
- case 0x13: // Horizontal Pixel Panning Register
- BX_VGA_THIS s.attribute_ctrl.horiz_pel_panning = (value & 0x0f);
- needs_update = 1;
-#if !defined(VGA_TRACE_FEATURE)
- BX_DEBUG(("io write 3c0: horiz pel panning = %02x",
- (unsigned) value));
-#endif
- break;
- case 0x14: // Color Select Register
- BX_VGA_THIS s.attribute_ctrl.color_select = (value & 0x0f);
- needs_update = 1;
-#if !defined(VGA_TRACE_FEATURE)
- BX_DEBUG(("io write 3c0: color select = %02x",
- (unsigned) BX_VGA_THIS s.attribute_ctrl.color_select));
-#endif
- break;
- default:
- BX_DEBUG(("io write 3c0: data-write mode %02x h",
- (unsigned) BX_VGA_THIS s.attribute_ctrl.address));
- }
- }
- BX_VGA_THIS s.attribute_ctrl.flip_flop = !BX_VGA_THIS s.attribute_ctrl.flip_flop;
- break;
-
- case 0x03c2: // Miscellaneous Output Register
- BX_VGA_THIS s.misc_output.color_emulation = (value >> 0) & 0x01;
- BX_VGA_THIS s.misc_output.enable_ram = (value >> 1) & 0x01;
- BX_VGA_THIS s.misc_output.clock_select = (value >> 2) & 0x03;
- BX_VGA_THIS s.misc_output.select_high_bank = (value >> 5) & 0x01;
- BX_VGA_THIS s.misc_output.horiz_sync_pol = (value >> 6) & 0x01;
- BX_VGA_THIS s.misc_output.vert_sync_pol = (value >> 7) & 0x01;
-#if !defined(VGA_TRACE_FEATURE)
- BX_DEBUG(("io write 3c2:"));
- BX_DEBUG((" color_emulation (attempted) = %u",
- (value >> 0) & 0x01));
- BX_DEBUG((" enable_ram = %u",
- (unsigned) BX_VGA_THIS s.misc_output.enable_ram));
- BX_DEBUG((" clock_select = %u",
- (unsigned) BX_VGA_THIS s.misc_output.clock_select));
- BX_DEBUG((" select_high_bank = %u",
- (unsigned) BX_VGA_THIS s.misc_output.select_high_bank));
- BX_DEBUG((" horiz_sync_pol = %u",
- (unsigned) BX_VGA_THIS s.misc_output.horiz_sync_pol));
- BX_DEBUG((" vert_sync_pol = %u",
- (unsigned) BX_VGA_THIS s.misc_output.vert_sync_pol));
-#endif
- break;
-
- case 0x03c3: // VGA enable
- // bit0: enables VGA display if set
-#if !defined(VGA_TRACE_FEATURE)
- BX_DEBUG(("io write 3c3: (ignoring) VGA enable = %u",
- (unsigned) (value & 0x01) ));
-#endif
- break;
-
- case 0x03c4: /* Sequencer Index Register */
- if (value > 4) {
- BX_DEBUG(("io write 3c4: value > 4"));
- }
- BX_VGA_THIS s.sequencer.index = value;
- break;
-
- case 0x03c5: /* Sequencer Registers 00..04 */
- switch (BX_VGA_THIS s.sequencer.index) {
- case 0: /* sequencer: reset */
-#if !defined(VGA_TRACE_FEATURE)
- BX_DEBUG(("write 0x3c5: sequencer reset: value=0x%02x",
- (unsigned) value));
-#endif
- if (BX_VGA_THIS s.sequencer.reset1 && ((value & 0x01) == 0)) {
- BX_VGA_THIS s.sequencer.char_map_select = 0;
- BX_VGA_THIS s.charmap_address = 0;
- bx_gui->set_text_charmap(
- & BX_VGA_THIS s.vga_memory[0x20000 + BX_VGA_THIS s.charmap_address]);
- BX_VGA_THIS s.vga_mem_updated = 1;
- }
- BX_VGA_THIS s.sequencer.reset1 = (value >> 0) & 0x01;
- BX_VGA_THIS s.sequencer.reset2 = (value >> 1) & 0x01;
- break;
- case 1: /* sequencer: clocking mode */
-#if !defined(VGA_TRACE_FEATURE)
- BX_DEBUG(("io write 3c5=%02x: clocking mode reg: ignoring",
- (unsigned) value));
-#endif
- BX_VGA_THIS s.sequencer.reg1 = value & 0x3f;
- BX_VGA_THIS s.x_dotclockdiv2 = ((value & 0x08) > 0);
- break;
- case 2: /* sequencer: map mask register */
- BX_VGA_THIS s.sequencer.map_mask = (value & 0x0f);
- for (i=0; i<4; i++)
- BX_VGA_THIS s.sequencer.map_mask_bit[i] = (value >> i) & 0x01;
- break;
- case 3: /* sequencer: character map select register */
- BX_VGA_THIS s.sequencer.char_map_select = value;
- charmap1 = value & 0x13;
- if (charmap1 > 3) charmap1 = (charmap1 & 3) + 4;
- charmap2 = (value & 0x2C) >> 2;
- if (charmap2 > 3) charmap2 = (charmap2 & 3) + 4;
- if (BX_VGA_THIS s.CRTC.reg[0x09] > 0) {
- BX_VGA_THIS s.charmap_address = (charmap1 << 13);
- bx_gui->set_text_charmap(
- & BX_VGA_THIS s.vga_memory[0x20000 + BX_VGA_THIS s.charmap_address]);
- BX_VGA_THIS s.vga_mem_updated = 1;
- }
- if (charmap2 != charmap1)
- BX_INFO(("char map select: #2=%d (unused)", charmap2));
- break;
- case 4: /* sequencer: memory mode register */
- BX_VGA_THIS s.sequencer.extended_mem = (value >> 1) & 0x01;
- BX_VGA_THIS s.sequencer.odd_even = (value >> 2) & 0x01;
- BX_VGA_THIS s.sequencer.chain_four = (value >> 3) & 0x01;
-
-#if !defined(VGA_TRACE_FEATURE)
- BX_DEBUG(("io write 3c5: index 4:"));
- BX_DEBUG((" extended_mem %u",
- (unsigned) BX_VGA_THIS s.sequencer.extended_mem));
- BX_DEBUG((" odd_even %u",
- (unsigned) BX_VGA_THIS s.sequencer.odd_even));
- BX_DEBUG((" chain_four %u",
- (unsigned) BX_VGA_THIS s.sequencer.chain_four));
-#endif
- break;
- default:
- BX_DEBUG(("io write 3c5: index %u unhandled",
- (unsigned) BX_VGA_THIS s.sequencer.index));
- }
- break;
-
- case 0x03c6: /* PEL mask */
- BX_VGA_THIS s.pel.mask = value;
- if (BX_VGA_THIS s.pel.mask != 0xff)
- BX_DEBUG(("io write 3c6: PEL mask=0x%02x != 0xFF", value));
- // BX_VGA_THIS s.pel.mask should be and'd with final value before
- // indexing into color register BX_VGA_THIS s.pel.data[]
- break;
-
- case 0x03c7: // PEL address, read mode
- BX_VGA_THIS s.pel.read_data_register = value;
- BX_VGA_THIS s.pel.read_data_cycle = 0;
- BX_VGA_THIS s.pel.dac_state = 0x03;
- break;
-
- case 0x03c8: /* PEL address write mode */
- BX_VGA_THIS s.pel.write_data_register = value;
- BX_VGA_THIS s.pel.write_data_cycle = 0;
- BX_VGA_THIS s.pel.dac_state = 0x00;
- break;
-
- case 0x03c9: /* PEL Data Register, colors 00..FF */
- switch (BX_VGA_THIS s.pel.write_data_cycle) {
- case 0:
- BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].red = value;
- break;
- case 1:
- BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].green = value;
- break;
- case 2:
- BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].blue = value;
-
- needs_update |= bx_gui->palette_change(BX_VGA_THIS s.pel.write_data_register,
- BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].red<<2,
- BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].green<<2,
- BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].blue<<2);
- break;
- }
-
- BX_VGA_THIS s.pel.write_data_cycle++;
- if (BX_VGA_THIS s.pel.write_data_cycle >= 3) {
- //BX_INFO(("BX_VGA_THIS s.pel.data[%u] {r=%u, g=%u, b=%u}",
- // (unsigned) BX_VGA_THIS s.pel.write_data_register,
- // (unsigned) BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].red,
- // (unsigned) BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].green,
- // (unsigned) BX_VGA_THIS s.pel.data[BX_VGA_THIS s.pel.write_data_register].blue);
- BX_VGA_THIS s.pel.write_data_cycle = 0;
- BX_VGA_THIS s.pel.write_data_register++;
- }
- break;
-
- case 0x03ca: /* Graphics 2 Position (EGA) */
- // ignore, EGA only???
- break;
-
- case 0x03cc: /* Graphics 1 Position (EGA) */
- // ignore, EGA only???
- break;
-
- case 0x03ce: /* Graphics Controller Index Register */
- if (value > 0x08) /* ??? */
- BX_DEBUG(("io write: 3ce: value > 8"));
- BX_VGA_THIS s.graphics_ctrl.index = value;
- break;
-
- case 0x03cd: /* ??? */
- BX_DEBUG(("io write to 03cd = %02x", (unsigned) value));
- break;
-
- case 0x03cf: /* Graphics Controller Registers 00..08 */
- switch (BX_VGA_THIS s.graphics_ctrl.index) {
- case 0: /* Set/Reset */
- BX_VGA_THIS s.graphics_ctrl.set_reset = value & 0x0f;
- break;
- case 1: /* Enable Set/Reset */
- BX_VGA_THIS s.graphics_ctrl.enable_set_reset = value & 0x0f;
- break;
- case 2: /* Color Compare */
- BX_VGA_THIS s.graphics_ctrl.color_compare = value & 0x0f;
- break;
- case 3: /* Data Rotate */
- BX_VGA_THIS s.graphics_ctrl.data_rotate = value & 0x07;
- /* ??? is this bits 3..4 or 4..5 */
- BX_VGA_THIS s.graphics_ctrl.raster_op = (value >> 3) & 0x03; /* ??? */
- break;
- case 4: /* Read Map Select */
- BX_VGA_THIS s.graphics_ctrl.read_map_select = value & 0x03;
-#if !defined(VGA_TRACE_FEATURE)
- BX_DEBUG(("io write to 03cf = %02x (RMS)", (unsigned) value));
-#endif
- break;
- case 5: /* Mode */
- BX_VGA_THIS s.graphics_ctrl.write_mode = value & 0x03;
- BX_VGA_THIS s.graphics_ctrl.read_mode = (value >> 3) & 0x01;
- BX_VGA_THIS s.graphics_ctrl.odd_even = (value >> 4) & 0x01;
- BX_VGA_THIS s.graphics_ctrl.shift_reg = (value >> 5) & 0x03;
-
- if (BX_VGA_THIS s.graphics_ctrl.odd_even)
- BX_DEBUG(("io write: 3cf: reg 05: value = %02xh",
- (unsigned) value));
- if (BX_VGA_THIS s.graphics_ctrl.shift_reg)
- BX_DEBUG(("io write: 3cf: reg 05: value = %02xh",
- (unsigned) value));
- break;
- case 6: /* Miscellaneous */
- prev_graphics_alpha = BX_VGA_THIS s.graphics_ctrl.graphics_alpha;
- prev_chain_odd_even = BX_VGA_THIS s.graphics_ctrl.chain_odd_even;
- prev_memory_mapping = BX_VGA_THIS s.graphics_ctrl.memory_mapping;
-
- BX_VGA_THIS s.graphics_ctrl.graphics_alpha = value & 0x01;
- BX_VGA_THIS s.graphics_ctrl.chain_odd_even = (value >> 1) & 0x01;
- BX_VGA_THIS s.graphics_ctrl.memory_mapping = (value >> 2) & 0x03;
-#if !defined(VGA_TRACE_FEATURE)
- BX_DEBUG(("memory_mapping set to %u",
- (unsigned) BX_VGA_THIS s.graphics_ctrl.memory_mapping));
- BX_DEBUG(("graphics mode set to %u",
- (unsigned) BX_VGA_THIS s.graphics_ctrl.graphics_alpha));
- BX_DEBUG(("odd_even mode set to %u",
- (unsigned) BX_VGA_THIS s.graphics_ctrl.odd_even));
- BX_DEBUG(("io write: 3cf: reg 06: value = %02xh",
- (unsigned) value));
-#endif
- if (prev_memory_mapping != BX_VGA_THIS s.graphics_ctrl.memory_mapping)
- needs_update = 1;
- if (prev_graphics_alpha != BX_VGA_THIS s.graphics_ctrl.graphics_alpha) {
- needs_update = 1;
- old_iHeight = 0;
- }
- break;
- case 7: /* Color Don't Care */
- BX_VGA_THIS s.graphics_ctrl.color_dont_care = value & 0x0f;
- break;
- case 8: /* Bit Mask */
- BX_VGA_THIS s.graphics_ctrl.bitmask = value;
- break;
- default:
- /* ??? */
- BX_DEBUG(("io write: 3cf: index %u unhandled",
- (unsigned) BX_VGA_THIS s.graphics_ctrl.index));
- }
- break;
-
- case 0x03b4: /* CRTC Index Register (monochrome emulation modes) */
- case 0x03d4: /* CRTC Index Register (color emulation modes) */
- BX_VGA_THIS s.CRTC.address = value & 0x7f;
- if (BX_VGA_THIS s.CRTC.address > 0x18)
- BX_DEBUG(("write: invalid CRTC register 0x%02x selected",
- (unsigned) BX_VGA_THIS s.CRTC.address));
- break;
-
- case 0x03b5: /* CRTC Registers (monochrome emulation modes) */
- case 0x03d5: /* CRTC Registers (color emulation modes) */
- if (BX_VGA_THIS s.CRTC.address > 0x18) {
- BX_DEBUG(("write: invalid CRTC register 0x%02x ignored",
- (unsigned) BX_VGA_THIS s.CRTC.address));
- return;
- }
- if (value != BX_VGA_THIS s.CRTC.reg[BX_VGA_THIS s.CRTC.address]) {
- BX_VGA_THIS s.CRTC.reg[BX_VGA_THIS s.CRTC.address] = value;
- switch (BX_VGA_THIS s.CRTC.address) {
- case 0x07:
- BX_VGA_THIS s.vertical_display_end &= 0xff;
- if (BX_VGA_THIS s.CRTC.reg[0x07] & 0x02) BX_VGA_THIS s.vertical_display_end |= 0x100;
- if (BX_VGA_THIS s.CRTC.reg[0x07] & 0x40) BX_VGA_THIS s.vertical_display_end |= 0x200;
- BX_VGA_THIS s.line_compare &= 0x2ff;
- if (BX_VGA_THIS s.CRTC.reg[0x07] & 0x10) BX_VGA_THIS s.line_compare |= 0x100;
- needs_update = 1;
- break;
- case 0x08:
- // Vertical pel panning change
- needs_update = 1;
- break;
- case 0x09:
- BX_VGA_THIS s.y_doublescan = ((value & 0x9f) > 0);
- BX_VGA_THIS s.line_compare &= 0x1ff;
- if (BX_VGA_THIS s.CRTC.reg[0x09] & 0x40) BX_VGA_THIS s.line_compare |= 0x200;
- needs_update = 1;
- break;
- case 0x0A:
- case 0x0B:
- case 0x0E:
- case 0x0F:
- // Cursor size / location change
- BX_VGA_THIS s.vga_mem_updated = 1;
- break;
- case 0x0C:
- case 0x0D:
- // Start address change
- if (BX_VGA_THIS s.graphics_ctrl.graphics_alpha) {
- needs_update = 1;
- } else {
- BX_VGA_THIS s.vga_mem_updated = 1;
- }
- break;
- case 0x12:
- BX_VGA_THIS s.vertical_display_end &= 0x300;
- BX_VGA_THIS s.vertical_display_end |= BX_VGA_THIS s.CRTC.reg[0x12];
- break;
- case 0x13:
- case 0x14:
- case 0x17:
- // Line offset change
- BX_VGA_THIS s.line_offset = BX_VGA_THIS s.CRTC.reg[0x13] << 1;
- if (BX_VGA_THIS s.CRTC.reg[0x14] & 0x40) BX_VGA_THIS s.line_offset <<= 2;
- else if ((BX_VGA_THIS s.CRTC.reg[0x17] & 0x40) == 0) BX_VGA_THIS s.line_offset <<= 1;
- needs_update = 1;
- break;
- case 0x18:
- BX_VGA_THIS s.line_compare &= 0x300;
- BX_VGA_THIS s.line_compare |= BX_VGA_THIS s.CRTC.reg[0x18];
- needs_update = 1;
- break;
- }
-
- }
- break;
-
- case 0x03da: /* Feature Control (color emulation modes) */
- BX_DEBUG(("io write: 3da: ignoring: feature ctrl & vert sync"));
- break;
-
- case 0x03c1: /* */
- default:
- BX_ERROR(("unsupported io write to port 0x%04x, val=0x%02x",
- (unsigned) address, (unsigned) value));
- }
- if (needs_update) {
- BX_VGA_THIS s.vga_mem_updated = 1;
- // Mark all video as updated so the changes will go through
- if ((BX_VGA_THIS s.graphics_ctrl.graphics_alpha)
-#if BX_SUPPORT_VBE
- || (BX_VGA_THIS s.vbe_enabled)
-#endif
- ) {
- for (unsigned xti = 0; xti < BX_NUM_X_TILES; xti++) {
- for (unsigned yti = 0; yti < BX_NUM_Y_TILES; yti++) {
- SET_TILE_UPDATED (xti, yti, 1);
- }
- }
- } else {
- memset(BX_VGA_THIS s.text_snapshot, 0,
- sizeof(BX_VGA_THIS s.text_snapshot));
- }
- }
-}
-
-void
-bx_vga_c::set_update_interval (unsigned interval)
-{
- BX_INFO (("Changing timer interval to %d\n", interval));
- BX_VGA_THIS timer_handler (theVga);
- bx_pc_system.activate_timer (BX_VGA_THIS timer_id, interval, 1);
-}
-
- void
-bx_vga_c::trigger_timer(void *this_ptr)
-{
- timer_handler(this_ptr);
-}
-
- void
-bx_vga_c::timer_handler(void *this_ptr)
-{
-#if !BX_USE_VGA_SMF
-
- bx_vga_c *class_ptr = (bx_vga_c *) this_ptr;
-
- class_ptr->timer();
-}
-
- void
-bx_vga_c::timer(void)
-{
-#else
- UNUSED(this_ptr);
-#endif
-
- update();
- bx_gui->flush();
-
-}
-
-
- void
-bx_vga_c::update(void)
-{
- unsigned iHeight, iWidth;
-
- /* no screen update necessary */
- if (BX_VGA_THIS s.vga_mem_updated==0)
- return;
-
- /* skip screen update when the sequencer is in reset mode or video is disabled */
- if (!BX_VGA_THIS s.sequencer.reset1 || !BX_VGA_THIS s.sequencer.reset2
- || !BX_VGA_THIS s.attribute_ctrl.video_enabled)
- return;
-
- /* skip screen update if the vertical retrace is in progress
- (using 72 Hz vertical frequency) */
- if ((bx_pc_system.time_usec() % 13888) < 70)
- return;
-
-#if BX_SUPPORT_VBE
- if ((BX_VGA_THIS s.vbe_enabled) && (BX_VGA_THIS s.vbe_bpp != VBE_DISPI_BPP_4))
- {
- // specific VBE code display update code
- // this is partly copied/modified from the 320x200x8 update more below
- unsigned xc, yc, xti, yti;
- unsigned r;
- unsigned long pixely, bmp_ofs_y, tile_ofs_y;
-
- if (BX_VGA_THIS s.vbe_bpp == VBE_DISPI_BPP_32)
- {
- Bit32u *vidmem = (Bit32u *)(&BX_VGA_THIS s.vbe_memory[BX_VGA_THIS s.vbe_virtual_start]);
- Bit32u *tile = (Bit32u *)(BX_VGA_THIS s.tile);
- Bit16u width = BX_VGA_THIS s.vbe_virtual_xres;
-
- Bit32u *vidptr, *tileptr;
-
- iWidth=BX_VGA_THIS s.vbe_xres;
- iHeight=BX_VGA_THIS s.vbe_yres;
-
- for (yc=0, yti = 0; yc<iHeight; yc+=Y_TILESIZE, yti++)
- {
- for (xc=0, xti = 0; xc<iWidth; xc+=X_TILESIZE, xti++)
- {
- if (GET_TILE_UPDATED (xti, yti))
- {
- for (r=0; r<Y_TILESIZE; r++)
- {
- pixely = yc + r;
- // calc offsets into video and tile memory
- bmp_ofs_y = pixely*width;
- tile_ofs_y = r*X_TILESIZE;
- // get offsets so that we do less calc in the inner loop
- vidptr = &vidmem[bmp_ofs_y+xc];
- tileptr = &tile[tile_ofs_y];
- memmove(tileptr, vidptr, X_TILESIZE<<2);
- }
- SET_TILE_UPDATED (xti, yti, 0);
- bx_gui->graphics_tile_update(BX_VGA_THIS s.tile, xc, yc);
- }
- }
- }
- }
- else if (BX_VGA_THIS s.vbe_bpp == VBE_DISPI_BPP_24)
- {
- Bit8u *vidmem = &BX_VGA_THIS s.vbe_memory[BX_VGA_THIS s.vbe_virtual_start];
- Bit8u *tile = BX_VGA_THIS s.tile;
- Bit16u width = BX_VGA_THIS s.vbe_virtual_xres*3;
-
- Bit8u *vidptr, *tileptr;
-
- iWidth=BX_VGA_THIS s.vbe_xres;
- iHeight=BX_VGA_THIS s.vbe_yres;
-
- for (yc=0, yti = 0; yc<iHeight; yc+=Y_TILESIZE, yti++)
- {
- for (xc=0, xti = 0; xc<iWidth; xc+=X_TILESIZE, xti++)
- {
- if (GET_TILE_UPDATED (xti, yti))
- {
- for (r=0; r<Y_TILESIZE; r++)
- {
- pixely = yc + r;
- // calc offsets into video and tile memory
- bmp_ofs_y = pixely*width;
- tile_ofs_y = r*X_TILESIZE*3;
- // get offsets so that we do less calc in the inner loop
- vidptr = &vidmem[bmp_ofs_y+xc*3];
- tileptr = &tile[tile_ofs_y];
- memmove(tileptr, vidptr, X_TILESIZE*3);
- }
- SET_TILE_UPDATED (xti, yti, 0);
- bx_gui->graphics_tile_update(BX_VGA_THIS s.tile, xc, yc);
- }
- }
- }
- }
- else if ((BX_VGA_THIS s.vbe_bpp == VBE_DISPI_BPP_15) ||
- (BX_VGA_THIS s.vbe_bpp == VBE_DISPI_BPP_16))
- {
- Bit16u *vidmem = (Bit16u *)(&BX_VGA_THIS s.vbe_memory[BX_VGA_THIS s.vbe_virtual_start]);
- Bit16u *tile = (Bit16u *)(BX_VGA_THIS s.tile);
- Bit16u width = BX_VGA_THIS s.vbe_virtual_xres;
-
- Bit16u *vidptr, *tileptr;
-
- iWidth=BX_VGA_THIS s.vbe_xres;
- iHeight=BX_VGA_THIS s.vbe_yres;
-
- for (yc=0, yti = 0; yc<iHeight; yc+=Y_TILESIZE, yti++)
- {
- for (xc=0, xti = 0; xc<iWidth; xc+=X_TILESIZE, xti++)
- {
- if (GET_TILE_UPDATED (xti, yti))
- {
- for (r=0; r<Y_TILESIZE; r++)
- {
- pixely = yc + r;
- // calc offsets into video and tile memory
- bmp_ofs_y = pixely*width;
- tile_ofs_y = r*X_TILESIZE;
- // get offsets so that we do less calc in the inner loop
- vidptr = &vidmem[bmp_ofs_y+xc];
- tileptr = &tile[tile_ofs_y];
- memmove(tileptr, vidptr, X_TILESIZE<<1);
- }
- SET_TILE_UPDATED (xti, yti, 0);
- bx_gui->graphics_tile_update(BX_VGA_THIS s.tile, xc, yc);
- }
- }
- }
- }
- else /* Update 8bpp mode */
- {
- Bit8u *vidmem = &BX_VGA_THIS s.vbe_memory[BX_VGA_THIS s.vbe_virtual_start];
- Bit8u *tile = BX_VGA_THIS s.tile;
- Bit16u width = BX_VGA_THIS s.vbe_virtual_xres;
-
- Bit8u *vidptr, *tileptr;
-
- iWidth=BX_VGA_THIS s.vbe_xres;
- iHeight=BX_VGA_THIS s.vbe_yres;
-
- for (yc=0, yti = 0; yc<iHeight; yc+=Y_TILESIZE, yti++)
- {
- for (xc=0, xti = 0; xc<iWidth; xc+=X_TILESIZE, xti++)
- {
- // If the tile has not been updated, copy it into the tile buffer for update
- if (GET_TILE_UPDATED (xti, yti)) {
- for (r=0; r<Y_TILESIZE; r++) {
- // actual video y coord is tile_y + y
- pixely = yc + r;
- // calc offsets into video and tile memory
- bmp_ofs_y = pixely*width;
- tile_ofs_y = r*X_TILESIZE;
- // get offsets so that we do less calc in the inner loop
- vidptr = &vidmem[bmp_ofs_y+xc];
- tileptr = &tile[tile_ofs_y];
- memmove(tileptr, vidptr, X_TILESIZE);
- }
- SET_TILE_UPDATED (xti, yti, 0);
- bx_gui->graphics_tile_update(BX_VGA_THIS s.tile, xc, yc);
- }
- }
- }
- }
-
- old_iWidth = iWidth;
- old_iHeight = iHeight;
- BX_VGA_THIS s.vga_mem_updated = 0;
- // after a vbe display update, don't try to do any 'normal vga' updates anymore
- return;
- }
-#endif
- // fields that effect the way video memory is serialized into screen output:
- // GRAPHICS CONTROLLER:
- // BX_VGA_THIS s.graphics_ctrl.shift_reg:
- // 0: output data in standard VGA format or CGA-compatible 640x200 2 color
- // graphics mode (mode 6)
- // 1: output data in CGA-compatible 320x200 4 color graphics mode
- // (modes 4 & 5)
- // 2: output data 8 bits at a time from the 4 bit planes
- // (mode 13 and variants like modeX)
-
- // if (BX_VGA_THIS s.vga_mem_updated==0 || BX_VGA_THIS s.attribute_ctrl.video_enabled == 0)
-
- if (BX_VGA_THIS s.graphics_ctrl.graphics_alpha) {
- Bit8u color;
- unsigned bit_no, r, c, x, y;
- unsigned long byte_offset, start_addr;
- unsigned xc, yc, xti, yti;
-
- start_addr = (BX_VGA_THIS s.CRTC.reg[0x0c] << 8) | BX_VGA_THIS s.CRTC.reg[0x0d];
-
-//BX_DEBUG(("update: shiftreg=%u, chain4=%u, mapping=%u",
-// (unsigned) BX_VGA_THIS s.graphics_ctrl.shift_reg,
-// (unsigned) BX_VGA_THIS s.sequencer.chain_four,
-// (unsigned) BX_VGA_THIS s.graphics_ctrl.memory_mapping);
-
- determine_screen_dimensions(&iHeight, &iWidth);
- if( (iWidth != old_iWidth) || (iHeight != old_iHeight) || (old_BPP > 8) ) {
- bx_gui->dimension_update(iWidth, iHeight);
- old_iWidth = iWidth;
- old_iHeight = iHeight;
- old_BPP = 8;
- }
-
- switch ( BX_VGA_THIS s.graphics_ctrl.shift_reg ) {
-
- case 0:
- Bit8u attribute, palette_reg_val, DAC_regno;
- unsigned long line_compare;
-
- if (BX_VGA_THIS s.graphics_ctrl.memory_mapping == 3) { // CGA 640x200x2
-
- for (yc=0, yti=0; yc<iHeight; yc+=Y_TILESIZE, yti++) {
- for (xc=0, xti=0; xc<iWidth; xc+=X_TILESIZE, xti++) {
- if (GET_TILE_UPDATED (xti, yti)) {
- for (r=0; r<Y_TILESIZE; r++) {
- y = yc + r;
- if (BX_VGA_THIS s.y_doublescan) y >>= 1;
- for (c=0; c<X_TILESIZE; c++) {
-
- x = xc + c;
- /* 0 or 0x2000 */
- byte_offset = start_addr + ((y & 1) << 13);
- /* to the start of the line */
- byte_offset += (320 / 4) * (y / 2);
- /* to the byte start */
- byte_offset += (x / 8);
-
- bit_no = 7 - (x % 8);
- palette_reg_val = (((BX_VGA_THIS s.vga_memory[byte_offset]) >> bit_no) & 1);
- DAC_regno = BX_VGA_THIS s.attribute_ctrl.palette_reg[palette_reg_val];
- BX_VGA_THIS s.tile[r*X_TILESIZE + c] = DAC_regno;
- }
- }
- SET_TILE_UPDATED (xti, yti, 0);
- bx_gui->graphics_tile_update(BX_VGA_THIS s.tile, xc, yc);
- }
- }
- }
- } else { // output data in serial fashion with each display plane
- // output on its associated serial output. Standard EGA/VGA format
-
- line_compare = BX_VGA_THIS s.line_compare;
- if (BX_VGA_THIS s.y_doublescan) line_compare >>= 1;
-
- for (yc=0, yti=0; yc<iHeight; yc+=Y_TILESIZE, yti++) {
- for (xc=0, xti=0; xc<iWidth; xc+=X_TILESIZE, xti++) {
- if (GET_TILE_UPDATED (xti, yti)) {
- for (r=0; r<Y_TILESIZE; r++) {
- y = yc + r;
- if (BX_VGA_THIS s.y_doublescan) y >>= 1;
- for (c=0; c<X_TILESIZE; c++) {
- x = xc + c;
- if (BX_VGA_THIS s.x_dotclockdiv2) x >>= 1;
- bit_no = 7 - (x % 8);
- if (y > line_compare) {
- byte_offset = x / 8 +
- ((y - line_compare - 1) * BX_VGA_THIS s.line_offset);
- } else {
- byte_offset = start_addr + x / 8 +
- (y * BX_VGA_THIS s.line_offset);
- }
- attribute =
- (((BX_VGA_THIS s.vga_memory[0*65536 + byte_offset] >> bit_no) & 0x01) << 0) |
- (((BX_VGA_THIS s.vga_memory[1*65536 + byte_offset] >> bit_no) & 0x01) << 1) |
- (((BX_VGA_THIS s.vga_memory[2*65536 + byte_offset] >> bit_no) & 0x01) << 2) |
- (((BX_VGA_THIS s.vga_memory[3*65536 + byte_offset] >> bit_no) & 0x01) << 3);
-
- attribute &= BX_VGA_THIS s.attribute_ctrl.color_plane_enable;
- // undocumented feature ???: colors 0..7 high intensity, colors 8..15 blinking
- // using low/high intensity. Blinking is not implemented yet.
- if (BX_VGA_THIS s.attribute_ctrl.mode_ctrl.blink_intensity) attribute ^= 0x08;
- palette_reg_val = BX_VGA_THIS s.attribute_ctrl.palette_reg[attribute];
- if (BX_VGA_THIS s.attribute_ctrl.mode_ctrl.internal_palette_size) {
- // use 4 lower bits from palette register
- // use 4 higher bits from color select register
- // 16 banks of 16-color registers
- DAC_regno = (palette_reg_val & 0x0f) |
- (BX_VGA_THIS s.attribute_ctrl.color_select << 4);
- }
- else {
- // use 6 lower bits from palette register
- // use 2 higher bits from color select register
- // 4 banks of 64-color registers
- DAC_regno = (palette_reg_val & 0x3f) |
- ((BX_VGA_THIS s.attribute_ctrl.color_select & 0x0c) << 4);
- }
- // DAC_regno &= video DAC mask register ???
-
- BX_VGA_THIS s.tile[r*X_TILESIZE + c] = DAC_regno;
- }
- }
- SET_TILE_UPDATED (xti, yti, 0);
- bx_gui->graphics_tile_update(BX_VGA_THIS s.tile, xc, yc);
- }
- }
- }
- }
- break; // case 0
-
- case 1: // output the data in a CGA-compatible 320x200 4 color graphics
- // mode. (modes 4 & 5)
-
- /* CGA 320x200x4 start */
-
- for (yc=0, yti=0; yc<iHeight; yc+=Y_TILESIZE, yti++) {
- for (xc=0, xti=0; xc<iWidth; xc+=X_TILESIZE, xti++) {
- if (GET_TILE_UPDATED (xti, yti)) {
- for (r=0; r<Y_TILESIZE; r++) {
- y = yc + r;
- if (BX_VGA_THIS s.y_doublescan) y >>= 1;
- for (c=0; c<X_TILESIZE; c++) {
-
- x = xc + c;
- if (BX_VGA_THIS s.x_dotclockdiv2) x >>= 1;
- /* 0 or 0x2000 */
- byte_offset = start_addr + ((y & 1) << 13);
- /* to the start of the line */
- byte_offset += (320 / 4) * (y / 2);
- /* to the byte start */
- byte_offset += (x / 4);
-
- attribute = 6 - 2*(x % 4);
- palette_reg_val = (BX_VGA_THIS s.vga_memory[byte_offset]) >> attribute;
- palette_reg_val &= 3;
- DAC_regno = BX_VGA_THIS s.attribute_ctrl.palette_reg[palette_reg_val];
- BX_VGA_THIS s.tile[r*X_TILESIZE + c] = DAC_regno;
- }
- }
- SET_TILE_UPDATED (xti, yti, 0);
- bx_gui->graphics_tile_update(BX_VGA_THIS s.tile, xc, yc);
- }
- }
- }
- /* CGA 320x200x4 end */
-
- break; // case 1
-
- case 2: // output the data eight bits at a time from the 4 bit plane
- // (format for VGA mode 13 hex)
-
- if ( BX_VGA_THIS s.sequencer.chain_four ) {
- unsigned long pixely, pixelx, plane;
- // bx_vga_dump_status();
-
- if (BX_VGA_THIS s.misc_output.select_high_bank != 1)
- BX_PANIC(("update: select_high_bank != 1"));
-
- for (yc=0, yti=0; yc<iHeight; yc+=Y_TILESIZE, yti++) {
- for (xc=0, xti=0; xc<iWidth; xc+=X_TILESIZE, xti++) {
- if (GET_TILE_UPDATED (xti, yti)) {
- for (r=0; r<Y_TILESIZE; r++) {
- pixely = yc + r;
- if (BX_VGA_THIS s.y_doublescan) pixely >>= 1;
- for (c=0; c<X_TILESIZE; c++) {
- pixelx = (xc + c) >> 1;
- plane = (pixelx % 4);
- byte_offset = start_addr + (plane * 65536) +
- (pixely * BX_VGA_THIS s.line_offset) + (pixelx & ~0x03);
- color = BX_VGA_THIS s.vga_memory[byte_offset];
- BX_VGA_THIS s.tile[r*X_TILESIZE + c] = color;
- }
- }
- SET_TILE_UPDATED (xti, yti, 0);
- bx_gui->graphics_tile_update(BX_VGA_THIS s.tile, xc, yc);
- }
- }
- }
- }
-
- else { // chain_four == 0, modeX
- unsigned long pixely, pixelx, plane;
-
- for (yc=0, yti=0; yc<iHeight; yc+=Y_TILESIZE, yti++) {
- for (xc=0, xti=0; xc<iWidth; xc+=X_TILESIZE, xti++) {
- if (GET_TILE_UPDATED (xti, yti)) {
- for (r=0; r<Y_TILESIZE; r++) {
- pixely = yc + r;
- if (BX_VGA_THIS s.y_doublescan) pixely >>= 1;
- for (c=0; c<X_TILESIZE; c++) {
- pixelx = (xc + c) >> 1;
- plane = (pixelx % 4);
- byte_offset = (plane * 65536) +
- (pixely * BX_VGA_THIS s.line_offset)
- + (pixelx >> 2);
- color = BX_VGA_THIS s.vga_memory[start_addr + byte_offset];
- BX_VGA_THIS s.tile[r*X_TILESIZE + c] = color;
- }
- }
- SET_TILE_UPDATED (xti, yti, 0);
- bx_gui->graphics_tile_update(BX_VGA_THIS s.tile, xc, yc);
- }
- }
- }
- }
- break; // case 2
-
- default:
- BX_PANIC(("update: shift_reg == %u", (unsigned)
- BX_VGA_THIS s.graphics_ctrl.shift_reg ));
- }
-
- BX_VGA_THIS s.vga_mem_updated = 0;
- return;
- }
-
- else { // text mode
- unsigned long start_address;
- unsigned long cursor_address, cursor_x, cursor_y;
- bx_vga_tminfo_t tm_info;
-
-
- tm_info.cs_start = BX_VGA_THIS s.CRTC.reg[0x0a] & 0x3f;
- tm_info.cs_end = BX_VGA_THIS s.CRTC.reg[0x0b] & 0x1f;
- tm_info.line_offset = BX_VGA_THIS s.CRTC.reg[0x13] << 2;
- tm_info.line_compare = BX_VGA_THIS s.line_compare;
- tm_info.h_panning = BX_VGA_THIS s.attribute_ctrl.horiz_pel_panning & 0x0f;
- tm_info.v_panning = BX_VGA_THIS s.CRTC.reg[0x08] & 0x1f;
- tm_info.line_graphics = BX_VGA_THIS s.attribute_ctrl.mode_ctrl.enable_line_graphics;
- if ((BX_VGA_THIS s.sequencer.reg1 & 0x01) == 0) {
- if (tm_info.h_panning == 8)
- tm_info.h_panning = 0;
- else
- tm_info.h_panning++;
- }
-
- switch (BX_VGA_THIS s.graphics_ctrl.memory_mapping) {
- case 0: // 128K @ A0000
- case 1: // 64K @ A0000
- iWidth = 8*80; // TODO: should use font size
- iHeight = 16*25;
- if( (iWidth != old_iWidth) || (iHeight != old_iHeight) || (old_BPP > 8) )
- {
- bx_gui->dimension_update(iWidth, iHeight, 16, 8);
- old_iWidth = iWidth;
- old_iHeight = iHeight;
- old_BPP = 8;
- }
- /* pass old text snapshot & new VGA memory contents */
- start_address = 0x0;
- cursor_address = 2*((BX_VGA_THIS s.CRTC.reg[0x0e] << 8) |
- BX_VGA_THIS s.CRTC.reg[0x0f]);
- if (cursor_address < start_address) {
- cursor_x = 0xffff;
- cursor_y = 0xffff;
- }
- else {
- cursor_x = ((cursor_address - start_address)/2) % 80;
- cursor_y = ((cursor_address - start_address)/2) / 80;
- }
- bx_gui->text_update(BX_VGA_THIS s.text_snapshot,
- &BX_VGA_THIS s.vga_memory[start_address],
- cursor_x, cursor_y, tm_info, 25);
- // screen updated, copy new VGA memory contents into text snapshot
- memcpy(BX_VGA_THIS s.text_snapshot,
- &BX_VGA_THIS s.vga_memory[start_address],
- 2*80*25);
- BX_VGA_THIS s.vga_mem_updated = 0;
- break;
-
- case 2: // B0000 .. B7FFF
- case 3: // B8000 .. BFFFF
- unsigned VDE, MSL, rows, cWidth;
-
- // Verticle Display End: find out how many lines are displayed
- VDE = BX_VGA_THIS s.vertical_display_end;
- // Maximum Scan Line: height of character cell
- MSL = BX_VGA_THIS s.CRTC.reg[0x09] & 0x1f;
- if (MSL == 0) {
- //BX_ERROR(("character height = 1, skipping text update"));
- return;
- }
- if ((MSL == 1) && (BX_VGA_THIS s.CRTC.reg[0x06] == 100)) {
- // emulated CGA graphics mode 160x100x16 colors
- MSL = 3;
- rows = 100;
- cWidth = 8;
- iWidth = cWidth * BX_VGA_THIS s.CRTC.reg[1];
- iHeight = 400;
- } else {
- rows = (VDE+1)/(MSL+1);
- if (rows > BX_MAX_TEXT_LINES)
- BX_PANIC(("text rows>%d: %d",BX_MAX_TEXT_LINES,rows));
- cWidth = ((BX_VGA_THIS s.sequencer.reg1 & 0x01) == 1) ? 8 : 9;
- iWidth = cWidth * (BX_VGA_THIS s.CRTC.reg[1] + 1);
- iHeight = VDE+1;
- }
- if( (iWidth != old_iWidth) || (iHeight != old_iHeight) || (MSL != old_MSL) || (old_BPP > 8) )
- {
- bx_gui->dimension_update(iWidth, iHeight, MSL+1, cWidth);
- old_iWidth = iWidth;
- old_iHeight = iHeight;
- old_MSL = MSL;
- old_BPP = 8;
- }
- // pass old text snapshot & new VGA memory contents
- start_address = 2*((BX_VGA_THIS s.CRTC.reg[12] << 8) + BX_VGA_THIS s.CRTC.reg[13]);
- cursor_address = 2*((BX_VGA_THIS s.CRTC.reg[0x0e] << 8) |
- BX_VGA_THIS s.CRTC.reg[0x0f]);
- if (cursor_address < start_address) {
- cursor_x = 0xffff;
- cursor_y = 0xffff;
- }
- else {
- cursor_x = ((cursor_address - start_address)/2) % (iWidth/cWidth);
- cursor_y = ((cursor_address - start_address)/2) / (iWidth/cWidth);
- }
- bx_gui->text_update(BX_VGA_THIS s.text_snapshot,
- &BX_VGA_THIS s.vga_memory[start_address],
- cursor_x, cursor_y, tm_info, rows);
- // screen updated, copy new VGA memory contents into text snapshot
- memcpy(BX_VGA_THIS s.text_snapshot,
- &BX_VGA_THIS s.vga_memory[start_address],
- 2*80*rows);
- BX_VGA_THIS s.vga_mem_updated = 0;
- break;
- default:
- BX_DEBUG(("update(): color text mode: mem map is %u",
- (unsigned) BX_VGA_THIS s.graphics_ctrl.memory_mapping));
- }
- }
-}
-
-
- Bit8u
-bx_vga_c::mem_read(Bit32u addr)
-{
- Bit32u offset;
-
-#if BX_SUPPORT_VBE
- // if in a vbe enabled mode, read from the vbe_memory
- if ((BX_VGA_THIS s.vbe_enabled) && (BX_VGA_THIS s.vbe_bpp != VBE_DISPI_BPP_4))
- {
- return vbe_mem_read(addr);
- }
-#endif
-
-#if defined(VGA_TRACE_FEATURE)
-// BX_DEBUG(("8-bit memory read from %08x", addr));
-#endif
-
-#ifdef __OS2__
-
-#if BX_PLUGINS
-#error Fix the code for plugins
-#endif
-
- if ( bx_options.videomode == BX_VIDEO_DIRECT )
- {
- char value;
-
- value = devices->mem->video[addr-0xA0000];
-
- return value;
- }
-#endif
-
- switch (BX_VGA_THIS s.graphics_ctrl.memory_mapping) {
- case 1: // 0xA0000 .. 0xAFFFF
- if (addr > 0xAFFFF) return 0xff;
- offset = addr - 0xA0000;
- break;
- case 2: // 0xB0000 .. 0xB7FFF
- if ((addr < 0xB0000) || (addr > 0xB7FFF)) return 0xff;
- return BX_VGA_THIS s.vga_memory[addr - 0xB0000];
- break;
- case 3: // 0xB8000 .. 0xBFFFF
- if (addr < 0xB8000) return 0xff;
- return BX_VGA_THIS s.vga_memory[addr - 0xB8000];
- break;
- default: // 0xA0000 .. 0xBFFFF
- return BX_VGA_THIS s.vga_memory[addr - 0xA0000];
- }
-
- // addr between 0xA0000 and 0xAFFFF
- if ( BX_VGA_THIS s.sequencer.chain_four ) {
-
- // Mode 13h: 320 x 200 256 color mode: chained pixel representation
- return BX_VGA_THIS s.vga_memory[(offset & ~0x03) + (offset % 4)*65536];
- }
-
- /* addr between 0xA0000 and 0xAFFFF */
- switch (BX_VGA_THIS s.graphics_ctrl.read_mode) {
- case 0: /* read mode 0 */
- BX_VGA_THIS s.graphics_ctrl.latch[0] = BX_VGA_THIS s.vga_memory[ offset];
- BX_VGA_THIS s.graphics_ctrl.latch[1] = BX_VGA_THIS s.vga_memory[1*65536 + offset];
- BX_VGA_THIS s.graphics_ctrl.latch[2] = BX_VGA_THIS s.vga_memory[2*65536 + offset];
- BX_VGA_THIS s.graphics_ctrl.latch[3] = BX_VGA_THIS s.vga_memory[3*65536 + offset];
- return(BX_VGA_THIS s.graphics_ctrl.latch[BX_VGA_THIS s.graphics_ctrl.read_map_select]);
- break;
-
- case 1: /* read mode 1 */
- {
- Bit8u color_compare, color_dont_care;
- Bit8u latch0, latch1, latch2, latch3, retval;
-
- color_compare = BX_VGA_THIS s.graphics_ctrl.color_compare & 0x0f;
- color_dont_care = BX_VGA_THIS s.graphics_ctrl.color_dont_care & 0x0f;
- latch0 = BX_VGA_THIS s.graphics_ctrl.latch[0] = BX_VGA_THIS s.vga_memory[ offset];
- latch1 = BX_VGA_THIS s.graphics_ctrl.latch[1] = BX_VGA_THIS s.vga_memory[1*65536 + offset];
- latch2 = BX_VGA_THIS s.graphics_ctrl.latch[2] = BX_VGA_THIS s.vga_memory[2*65536 + offset];
- latch3 = BX_VGA_THIS s.graphics_ctrl.latch[3] = BX_VGA_THIS s.vga_memory[3*65536 + offset];
-
- latch0 ^= ccdat[color_compare][0];
- latch1 ^= ccdat[color_compare][1];
- latch2 ^= ccdat[color_compare][2];
- latch3 ^= ccdat[color_compare][3];
-
- latch0 &= ccdat[color_dont_care][0];
- latch1 &= ccdat[color_dont_care][1];
- latch2 &= ccdat[color_dont_care][2];
- latch3 &= ccdat[color_dont_care][3];
-
- retval = ~(latch0 | latch1 | latch2 | latch3);
-
- return retval;
- }
- break;
- default:
- return 0;
- }
-}
-
- void
-bx_vga_c::mem_write(Bit32u addr, Bit8u value)
-{
- Bit32u offset;
- Bit8u new_val[4];
- unsigned start_addr;
-
-#if BX_SUPPORT_VBE
- // if in a vbe enabled mode, write to the vbe_memory
- if ((BX_VGA_THIS s.vbe_enabled) && (BX_VGA_THIS s.vbe_bpp != VBE_DISPI_BPP_4))
- {
- vbe_mem_write(addr,value);
- return;
- }
-#endif
-
-#if defined(VGA_TRACE_FEATURE)
-// BX_DEBUG(("8-bit memory write to %08x = %02x", addr, value));
-#endif
-
-#ifdef __OS2__
-
-#if BX_PLUGINS
-#error Fix the code for plugins
-#endif
-
- if ( bx_options.videomode == BX_VIDEO_DIRECT )
- {
- devices->mem->video[addr-0xA0000] = value;
-
- return;
- }
-#endif
-
- switch (BX_VGA_THIS s.graphics_ctrl.memory_mapping) {
- case 1: // 0xA0000 .. 0xAFFFF
- if (addr > 0xAFFFF) return;
- offset = addr - 0xA0000;
- break;
- case 2: // 0xB0000 .. 0xB7FFF
- if ((addr < 0xB0000) || (addr > 0xB7FFF)) return;
- offset = addr - 0xB0000;
- break;
- case 3: // 0xB8000 .. 0xBFFFF
- if (addr < 0xB8000) return;
- offset = addr - 0xB8000;
- break;
- default: // 0xA0000 .. 0xBFFFF
- offset = addr - 0xA0000;
- }
-
- start_addr = (BX_VGA_THIS s.CRTC.reg[0x0c] << 8) | BX_VGA_THIS s.CRTC.reg[0x0d];
-
- if (BX_VGA_THIS s.graphics_ctrl.graphics_alpha) {
- if (BX_VGA_THIS s.graphics_ctrl.memory_mapping == 3) { // 0xB8000 .. 0xBFFFF
- unsigned x_tileno, x_tileno2, y_tileno;
-
- /* CGA 320x200x4 / 640x200x2 start */
- BX_VGA_THIS s.vga_memory[offset] = value;
- offset -= start_addr;
- if (offset>=0x2000) {
- y_tileno = offset - 0x2000;
- y_tileno /= (320/4);
- y_tileno <<= 1; //2 * y_tileno;
- y_tileno++;
- x_tileno = (offset - 0x2000) % (320/4);
- x_tileno <<= 2; //*= 4;
- } else {
- y_tileno = offset / (320/4);
- y_tileno <<= 1; //2 * y_tileno;
- x_tileno = offset % (320/4);
- x_tileno <<= 2; //*=4;
- }
- x_tileno2=x_tileno;
- if (BX_VGA_THIS s.graphics_ctrl.shift_reg==0) {
- x_tileno*=2;
- x_tileno2+=7;
- } else {
- x_tileno2+=3;
- }
- if (BX_VGA_THIS s.x_dotclockdiv2) {
- x_tileno/=(X_TILESIZE/2);
- x_tileno2/=(X_TILESIZE/2);
- } else {
- x_tileno/=X_TILESIZE;
- x_tileno2/=X_TILESIZE;
- }
- if (BX_VGA_THIS s.y_doublescan) {
- y_tileno/=(Y_TILESIZE/2);
- } else {
- y_tileno/=Y_TILESIZE;
- }
- BX_VGA_THIS s.vga_mem_updated = 1;
- SET_TILE_UPDATED (x_tileno, y_tileno, 1);
- if (x_tileno2!=x_tileno) {
- SET_TILE_UPDATED (x_tileno2, y_tileno, 1);
- }
- return;
- /* CGA 320x200x4 / 640x200x2 end */
- }
- else if (BX_VGA_THIS s.graphics_ctrl.memory_mapping != 1) {
-
- BX_PANIC(("mem_write: graphics: mapping = %u",
- (unsigned) BX_VGA_THIS s.graphics_ctrl.memory_mapping));
- return;
- }
-
- if ( BX_VGA_THIS s.sequencer.chain_four ) {
- unsigned x_tileno, y_tileno;
-
- // 320 x 200 256 color mode: chained pixel representation
- BX_VGA_THIS s.vga_memory[(offset & ~0x03) + (offset % 4)*65536] = value;
- offset -= start_addr;
- x_tileno = (offset % BX_VGA_THIS s.line_offset) / (X_TILESIZE/2);
- if (BX_VGA_THIS s.y_doublescan) {
- y_tileno = (offset / BX_VGA_THIS s.line_offset) / (Y_TILESIZE/2);
- } else {
- y_tileno = (offset / BX_VGA_THIS s.line_offset) / Y_TILESIZE;
- }
- BX_VGA_THIS s.vga_mem_updated = 1;
- SET_TILE_UPDATED (x_tileno, y_tileno, 1);
- return;
- }
-
- }
-
- /* addr between 0xA0000 and 0xAFFFF */
- switch (BX_VGA_THIS s.graphics_ctrl.write_mode) {
- unsigned i;
-
- case 0: /* write mode 0 */
- {
- const Bit8u bitmask = BX_VGA_THIS s.graphics_ctrl.bitmask;
- const Bit8u set_reset = BX_VGA_THIS s.graphics_ctrl.set_reset;
- const Bit8u enable_set_reset = BX_VGA_THIS s.graphics_ctrl.enable_set_reset;
- /* perform rotate on CPU data in case its needed */
- if (BX_VGA_THIS s.graphics_ctrl.data_rotate) {
- value = (value >> BX_VGA_THIS s.graphics_ctrl.data_rotate) |
- (value << (8 - BX_VGA_THIS s.graphics_ctrl.data_rotate));
- }
- new_val[0] = BX_VGA_THIS s.graphics_ctrl.latch[0] & ~bitmask;
- new_val[1] = BX_VGA_THIS s.graphics_ctrl.latch[1] & ~bitmask;
- new_val[2] = BX_VGA_THIS s.graphics_ctrl.latch[2] & ~bitmask;
- new_val[3] = BX_VGA_THIS s.graphics_ctrl.latch[3] & ~bitmask;
- switch (BX_VGA_THIS s.graphics_ctrl.raster_op) {
- case 0: // replace
- new_val[0] |= ((enable_set_reset & 1)
- ? ((set_reset & 1) ? bitmask : 0)
- : (value & bitmask));
- new_val[1] |= ((enable_set_reset & 2)
- ? ((set_reset & 2) ? bitmask : 0)
- : (value & bitmask));
- new_val[2] |= ((enable_set_reset & 4)
- ? ((set_reset & 4) ? bitmask : 0)
- : (value & bitmask));
- new_val[3] |= ((enable_set_reset & 8)
- ? ((set_reset & 8) ? bitmask : 0)
- : (value & bitmask));
- break;
- case 1: // AND
- new_val[0] |= ((enable_set_reset & 1)
- ? ((set_reset & 1)
- ? (BX_VGA_THIS s.graphics_ctrl.latch[0] & bitmask)
- : 0)
- : (value & BX_VGA_THIS s.graphics_ctrl.latch[0]) & bitmask);
- new_val[1] |= ((enable_set_reset & 2)
- ? ((set_reset & 2)
- ? (BX_VGA_THIS s.graphics_ctrl.latch[1] & bitmask)
- : 0)
- : (value & BX_VGA_THIS s.graphics_ctrl.latch[1]) & bitmask);
- new_val[2] |= ((enable_set_reset & 4)
- ? ((set_reset & 4)
- ? (BX_VGA_THIS s.graphics_ctrl.latch[2] & bitmask)
- : 0)
- : (value & BX_VGA_THIS s.graphics_ctrl.latch[2]) & bitmask);
- new_val[3] |= ((enable_set_reset & 8)
- ? ((set_reset & 8)
- ? (BX_VGA_THIS s.graphics_ctrl.latch[3] & bitmask)
- : 0)
- : (value & BX_VGA_THIS s.graphics_ctrl.latch[3]) & bitmask);
- break;
- case 2: // OR
- new_val[0]
- |= ((enable_set_reset & 1)
- ? ((set_reset & 1)
- ? bitmask
- : (BX_VGA_THIS s.graphics_ctrl.latch[0] & bitmask))
- : ((value | BX_VGA_THIS s.graphics_ctrl.latch[0]) & bitmask));
- new_val[1]
- |= ((enable_set_reset & 2)
- ? ((set_reset & 2)
- ? bitmask
- : (BX_VGA_THIS s.graphics_ctrl.latch[1] & bitmask))
- : ((value | BX_VGA_THIS s.graphics_ctrl.latch[1]) & bitmask));
- new_val[2]
- |= ((enable_set_reset & 4)
- ? ((set_reset & 4)
- ? bitmask
- : (BX_VGA_THIS s.graphics_ctrl.latch[2] & bitmask))
- : ((value | BX_VGA_THIS s.graphics_ctrl.latch[2]) & bitmask));
- new_val[3]
- |= ((enable_set_reset & 8)
- ? ((set_reset & 8)
- ? bitmask
- : (BX_VGA_THIS s.graphics_ctrl.latch[3] & bitmask))
- : ((value | BX_VGA_THIS s.graphics_ctrl.latch[3]) & bitmask));
- break;
- case 3: // XOR
- new_val[0]
- |= ((enable_set_reset & 1)
- ? ((set_reset & 1)
- ? (~BX_VGA_THIS s.graphics_ctrl.latch[0] & bitmask)
- : (BX_VGA_THIS s.graphics_ctrl.latch[0] & bitmask))
- : (value ^ BX_VGA_THIS s.graphics_ctrl.latch[0]) & bitmask);
- new_val[1]
- |= ((enable_set_reset & 2)
- ? ((set_reset & 2)
- ? (~BX_VGA_THIS s.graphics_ctrl.latch[1] & bitmask)
- : (BX_VGA_THIS s.graphics_ctrl.latch[1] & bitmask))
- : (value ^ BX_VGA_THIS s.graphics_ctrl.latch[1]) & bitmask);
- new_val[2]
- |= ((enable_set_reset & 4)
- ? ((set_reset & 4)
- ? (~BX_VGA_THIS s.graphics_ctrl.latch[2] & bitmask)
- : (BX_VGA_THIS s.graphics_ctrl.latch[2] & bitmask))
- : (value ^ BX_VGA_THIS s.graphics_ctrl.latch[2]) & bitmask);
- new_val[3]
- |= ((enable_set_reset & 8)
- ? ((set_reset & 8)
- ? (~BX_VGA_THIS s.graphics_ctrl.latch[3] & bitmask)
- : (BX_VGA_THIS s.graphics_ctrl.latch[3] & bitmask))
- : (value ^ BX_VGA_THIS s.graphics_ctrl.latch[3]) & bitmask);
- break;
- default:
- BX_PANIC(("vga_mem_write: write mode 0: op = %u",
- (unsigned) BX_VGA_THIS s.graphics_ctrl.raster_op));
- }
- }
- break;
-
- case 1: /* write mode 1 */
- for (i=0; i<4; i++ ) {
- new_val[i] = BX_VGA_THIS s.graphics_ctrl.latch[i];
- }
- break;
-
- case 2: /* write mode 2 */
- {
- const Bit8u bitmask = BX_VGA_THIS s.graphics_ctrl.bitmask;
-
- new_val[0] = BX_VGA_THIS s.graphics_ctrl.latch[0] & ~bitmask;
- new_val[1] = BX_VGA_THIS s.graphics_ctrl.latch[1] & ~bitmask;
- new_val[2] = BX_VGA_THIS s.graphics_ctrl.latch[2] & ~bitmask;
- new_val[3] = BX_VGA_THIS s.graphics_ctrl.latch[3] & ~bitmask;
- switch (BX_VGA_THIS s.graphics_ctrl.raster_op) {
- case 0: // write
- new_val[0] |= (value & 1) ? bitmask : 0;
- new_val[1] |= (value & 2) ? bitmask : 0;
- new_val[2] |= (value & 4) ? bitmask : 0;
- new_val[3] |= (value & 8) ? bitmask : 0;
- break;
- case 1: // AND
- new_val[0] |= (value & 1)
- ? (BX_VGA_THIS s.graphics_ctrl.latch[0] & bitmask)
- : 0;
- new_val[1] |= (value & 2)
- ? (BX_VGA_THIS s.graphics_ctrl.latch[1] & bitmask)
- : 0;
- new_val[2] |= (value & 4)
- ? (BX_VGA_THIS s.graphics_ctrl.latch[2] & bitmask)
- : 0;
- new_val[3] |= (value & 8)
- ? (BX_VGA_THIS s.graphics_ctrl.latch[3] & bitmask)
- : 0;
- break;
- case 2: // OR
- new_val[0] |= (value & 1)
- ? bitmask
- : (BX_VGA_THIS s.graphics_ctrl.latch[0] & bitmask);
- new_val[1] |= (value & 2)
- ? bitmask
- : (BX_VGA_THIS s.graphics_ctrl.latch[1] & bitmask);
- new_val[2] |= (value & 4)
- ? bitmask
- : (BX_VGA_THIS s.graphics_ctrl.latch[2] & bitmask);
- new_val[3] |= (value & 8)
- ? bitmask
- : (BX_VGA_THIS s.graphics_ctrl.latch[3] & bitmask);
- break;
- case 3: // XOR
- new_val[0] |= (value & 1)
- ? (~BX_VGA_THIS s.graphics_ctrl.latch[0] & bitmask)
- : (BX_VGA_THIS s.graphics_ctrl.latch[0] & bitmask);
- new_val[1] |= (value & 2)
- ? (~BX_VGA_THIS s.graphics_ctrl.latch[1] & bitmask)
- : (BX_VGA_THIS s.graphics_ctrl.latch[1] & bitmask);
- new_val[2] |= (value & 4)
- ? (~BX_VGA_THIS s.graphics_ctrl.latch[2] & bitmask)
- : (BX_VGA_THIS s.graphics_ctrl.latch[2] & bitmask);
- new_val[3] |= (value & 8)
- ? (~BX_VGA_THIS s.graphics_ctrl.latch[3] & bitmask)
- : (BX_VGA_THIS s.graphics_ctrl.latch[3] & bitmask);
- break;
- }
- }
- break;
-
- case 3: /* write mode 3 */
- {
- const Bit8u bitmask = BX_VGA_THIS s.graphics_ctrl.bitmask & value;
- const Bit8u set_reset = BX_VGA_THIS s.graphics_ctrl.set_reset;
-
- /* perform rotate on CPU data */
- if (BX_VGA_THIS s.graphics_ctrl.data_rotate) {
- value = (value >> BX_VGA_THIS s.graphics_ctrl.data_rotate) |
- (value << (8 - BX_VGA_THIS s.graphics_ctrl.data_rotate));
- }
- new_val[0] = BX_VGA_THIS s.graphics_ctrl.latch[0] & ~bitmask;
- new_val[1] = BX_VGA_THIS s.graphics_ctrl.latch[1] & ~bitmask;
- new_val[2] = BX_VGA_THIS s.graphics_ctrl.latch[2] & ~bitmask;
- new_val[3] = BX_VGA_THIS s.graphics_ctrl.latch[3] & ~bitmask;
-
- value &= bitmask;
-
- switch (BX_VGA_THIS s.graphics_ctrl.raster_op) {
- case 0: // write
- new_val[0] |= (set_reset & 1) ? value : 0;
- new_val[1] |= (set_reset & 2) ? value : 0;
- new_val[2] |= (set_reset & 4) ? value : 0;
- new_val[3] |= (set_reset & 8) ? value : 0;
- break;
- case 1: // AND
- new_val[0] |= ((set_reset & 1) ? value : 0)
- & BX_VGA_THIS s.graphics_ctrl.latch[0];
- new_val[1] |= ((set_reset & 2) ? value : 0)
- & BX_VGA_THIS s.graphics_ctrl.latch[1];
- new_val[2] |= ((set_reset & 4) ? value : 0)
- & BX_VGA_THIS s.graphics_ctrl.latch[2];
- new_val[3] |= ((set_reset & 8) ? value : 0)
- & BX_VGA_THIS s.graphics_ctrl.latch[3];
- break;
- case 2: // OR
- new_val[0] |= ((set_reset & 1) ? value : 0)
- | BX_VGA_THIS s.graphics_ctrl.latch[0];
- new_val[1] |= ((set_reset & 2) ? value : 0)
- | BX_VGA_THIS s.graphics_ctrl.latch[1];
- new_val[2] |= ((set_reset & 4) ? value : 0)
- | BX_VGA_THIS s.graphics_ctrl.latch[2];
- new_val[3] |= ((set_reset & 8) ? value : 0)
- | BX_VGA_THIS s.graphics_ctrl.latch[3];
- break;
- case 3: // XOR
- new_val[0] |= ((set_reset & 1) ? value : 0)
- ^ BX_VGA_THIS s.graphics_ctrl.latch[0];
- new_val[1] |= ((set_reset & 2) ? value : 0)
- ^ BX_VGA_THIS s.graphics_ctrl.latch[1];
- new_val[2] |= ((set_reset & 4) ? value : 0)
- ^ BX_VGA_THIS s.graphics_ctrl.latch[2];
- new_val[3] |= ((set_reset & 8) ? value : 0)
- ^ BX_VGA_THIS s.graphics_ctrl.latch[3];
- break;
- }
- }
- break;
-
- default:
- BX_PANIC(("vga_mem_write: write mode %u ?",
- (unsigned) BX_VGA_THIS s.graphics_ctrl.write_mode));
- }
-
- if (BX_VGA_THIS s.sequencer.map_mask & 0x0f) {
- BX_VGA_THIS s.vga_mem_updated = 1;
- if (BX_VGA_THIS s.sequencer.map_mask_bit[0])
- BX_VGA_THIS s.vga_memory[0*65536 + offset] = new_val[0];
- if (BX_VGA_THIS s.sequencer.map_mask_bit[1])
- BX_VGA_THIS s.vga_memory[1*65536 + offset] = new_val[1];
- if (BX_VGA_THIS s.sequencer.map_mask_bit[2]) {
- if ((!BX_VGA_THIS s.graphics_ctrl.graphics_alpha) &&
- ((offset & 0xe000) == BX_VGA_THIS s.charmap_address)) {
- bx_gui->set_text_charbyte((offset & 0x1fff), new_val[2]);
- }
- BX_VGA_THIS s.vga_memory[2*65536 + offset] = new_val[2];
- }
- if (BX_VGA_THIS s.sequencer.map_mask_bit[3])
- BX_VGA_THIS s.vga_memory[3*65536 + offset] = new_val[3];
-
- unsigned x_tileno, y_tileno;
-
- if (BX_VGA_THIS s.graphics_ctrl.shift_reg == 2) {
- offset -= start_addr;
- x_tileno = (offset % BX_VGA_THIS s.line_offset) * 4 / (X_TILESIZE / 2);
- if (BX_VGA_THIS s.y_doublescan) {
- y_tileno = (offset / BX_VGA_THIS s.line_offset) / (Y_TILESIZE / 2);
- } else {
- y_tileno = (offset / BX_VGA_THIS s.line_offset) / Y_TILESIZE;
- }
- SET_TILE_UPDATED (x_tileno, y_tileno, 1);
- } else {
- if (BX_VGA_THIS s.line_compare < BX_VGA_THIS s.vertical_display_end) {
- if (BX_VGA_THIS s.x_dotclockdiv2) {
- x_tileno = (offset % BX_VGA_THIS s.line_offset) / (X_TILESIZE / 16);
- } else {
- x_tileno = (offset % BX_VGA_THIS s.line_offset) / (X_TILESIZE / 8);
- }
- if (BX_VGA_THIS s.y_doublescan) {
- y_tileno = ((offset / BX_VGA_THIS s.line_offset) * 2 + BX_VGA_THIS s.line_compare + 1) / Y_TILESIZE;
- } else {
- y_tileno = ((offset / BX_VGA_THIS s.line_offset) + BX_VGA_THIS s.line_compare + 1) / Y_TILESIZE;
- }
- SET_TILE_UPDATED (x_tileno, y_tileno, 1);
- }
- if (offset >= start_addr) {
- offset -= start_addr;
- if (BX_VGA_THIS s.x_dotclockdiv2) {
- x_tileno = (offset % BX_VGA_THIS s.line_offset) / (X_TILESIZE / 16);
- } else {
- x_tileno = (offset % BX_VGA_THIS s.line_offset) / (X_TILESIZE / 8);
- }
- if (BX_VGA_THIS s.y_doublescan) {
- y_tileno = (offset / BX_VGA_THIS s.line_offset) / (Y_TILESIZE / 2);
- } else {
- y_tileno = (offset / BX_VGA_THIS s.line_offset) / Y_TILESIZE;
- }
- SET_TILE_UPDATED (x_tileno, y_tileno, 1);
- }
- }
- }
-}
-
- void
-bx_vga_c::get_text_snapshot(Bit8u **text_snapshot, unsigned *txHeight,
- unsigned *txWidth)
-{
- unsigned VDE, MSL;
-
- if (!BX_VGA_THIS s.graphics_ctrl.graphics_alpha) {
- *text_snapshot = &BX_VGA_THIS s.text_snapshot[0];
- VDE = BX_VGA_THIS s.vertical_display_end;
- MSL = BX_VGA_THIS s.CRTC.reg[0x09] & 0x1f;
- *txHeight = (VDE+1)/(MSL+1);
- *txWidth = BX_VGA_THIS s.CRTC.reg[1] + 1;
- } else {
- *txHeight = 0;
- *txWidth = 0;
- }
-}
-
- Bit8u
-bx_vga_c::get_actl_palette_idx(Bit8u index)
-{
- return BX_VGA_THIS s.attribute_ctrl.palette_reg[index];
-}
-
- void
-bx_vga_c::dump_status(void)
-{
- BX_INFO(("s.misc_output.color_emulation = %u",
- (unsigned) BX_VGA_THIS s.misc_output.color_emulation));
- BX_INFO(("s.misc_output.enable_ram = %u",
- (unsigned) BX_VGA_THIS s.misc_output.enable_ram));
- BX_INFO(("s.misc_output.clock_select = %u",
- (unsigned) BX_VGA_THIS s.misc_output.clock_select));
- if (BX_VGA_THIS s.misc_output.clock_select == 0)
- BX_INFO((" 25Mhz 640 horiz pixel clock"));
- else
- BX_INFO((" 28Mhz 720 horiz pixel clock"));
- BX_INFO(("s.misc_output.select_high_bank = %u",
- (unsigned) BX_VGA_THIS s.misc_output.select_high_bank));
- BX_INFO(("s.misc_output.horiz_sync_pol = %u",
- (unsigned) BX_VGA_THIS s.misc_output.horiz_sync_pol));
- BX_INFO(("s.misc_output.vert_sync_pol = %u",
- (unsigned) BX_VGA_THIS s.misc_output.vert_sync_pol));
- switch ( (BX_VGA_THIS s.misc_output.vert_sync_pol << 1) |
- BX_VGA_THIS s.misc_output.horiz_sync_pol ) {
- case 0: BX_INFO((" (reserved")); break;
- case 1: BX_INFO((" 400 lines")); break;
- case 2: BX_INFO((" 350 lines")); break;
- case 3: BX_INFO((" 480 lines")); break;
- default: BX_INFO((" ???"));
- }
-
- BX_INFO(("s.graphics_ctrl.odd_even = %u",
- (unsigned) BX_VGA_THIS s.graphics_ctrl.odd_even));
- BX_INFO(("s.graphics_ctrl.chain_odd_even = %u",
- (unsigned) BX_VGA_THIS s.graphics_ctrl.chain_odd_even));
- BX_INFO(("s.graphics_ctrl.shift_reg = %u",
- (unsigned) BX_VGA_THIS s.graphics_ctrl.shift_reg));
- BX_INFO(("s.graphics_ctrl.graphics_alpha = %u",
- (unsigned) BX_VGA_THIS s.graphics_ctrl.graphics_alpha));
- BX_INFO(("s.graphics_ctrl.memory_mapping = %u",
- (unsigned) BX_VGA_THIS s.graphics_ctrl.memory_mapping));
- switch (BX_VGA_THIS s.graphics_ctrl.memory_mapping) {
- case 0: BX_INFO((" A0000-BFFFF")); break;
- case 1: BX_INFO((" A0000-AFFFF")); break;
- case 2: BX_INFO((" B0000-B7FFF")); break;
- case 3: BX_INFO((" B8000-BFFFF")); break;
- default: BX_INFO((" ???"));
- }
-
- BX_INFO(("s.sequencer.extended_mem = %u",
- (unsigned) BX_VGA_THIS s.sequencer.extended_mem));
- BX_INFO(("s.sequencer.odd_even = %u (inverted)",
- (unsigned) BX_VGA_THIS s.sequencer.odd_even));
- BX_INFO(("s.sequencer.chain_four = %u",
- (unsigned) BX_VGA_THIS s.sequencer.chain_four));
-
- BX_INFO(("s.attribute_ctrl.video_enabled = %u",
- (unsigned) BX_VGA_THIS s.attribute_ctrl.video_enabled));
- BX_INFO(("s.attribute_ctrl.mode_ctrl.graphics_alpha = %u",
- (unsigned) BX_VGA_THIS s.attribute_ctrl.mode_ctrl.graphics_alpha));
- BX_INFO(("s.attribute_ctrl.mode_ctrl.display_type = %u",
- (unsigned) BX_VGA_THIS s.attribute_ctrl.mode_ctrl.display_type));
- BX_INFO(("s.attribute_ctrl.mode_ctrl.internal_palette_size = %u",
- (unsigned) BX_VGA_THIS s.attribute_ctrl.mode_ctrl.internal_palette_size));
- BX_INFO(("s.attribute_ctrl.mode_ctrl.pixel_clock_select = %u",
- (unsigned) BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_clock_select));
-}
-
-
- void
-bx_vga_c::redraw_area(unsigned x0, unsigned y0, unsigned width,
- unsigned height)
-{
- unsigned xi, yi, x1, y1, xmax, ymax;
-
- BX_VGA_THIS s.vga_mem_updated = 1;
-
-#if BX_SUPPORT_VBE
- if (BX_VGA_THIS s.graphics_ctrl.graphics_alpha || BX_VGA_THIS s.vbe_enabled) {
-#else
- if (BX_VGA_THIS s.graphics_ctrl.graphics_alpha) {
-#endif
- // graphics mode
- x1 = x0 + width - 1;
- y1 = y0 + height - 1;
-
- xmax = old_iWidth;
- ymax = old_iHeight;
-#if BX_SUPPORT_VBE
- if (BX_VGA_THIS s.vbe_enabled) {
- xmax = BX_VGA_THIS s.vbe_xres;
- ymax = BX_VGA_THIS s.vbe_yres;
- }
-#endif
- for (yi=0; yi<ymax; yi+=Y_TILESIZE) {
- for (xi=0; xi<xmax; xi+=X_TILESIZE) {
- // is redraw rectangle outside x boundaries of this tile?
- if (x1 < xi) continue;
- if (x0 > (xi+X_TILESIZE-1)) continue;
-
- // is redraw rectangle outside y boundaries of this tile?
- if (y1 < yi) continue;
- if (y0 > (yi+Y_TILESIZE-1)) continue;
- unsigned xti = xi/X_TILESIZE;
- unsigned yti = yi/Y_TILESIZE;
- SET_TILE_UPDATED (xti, yti, 1);
- }
- }
- }
- else {
- // text mode
- memset(BX_VGA_THIS s.text_snapshot, 0,
- sizeof(BX_VGA_THIS s.text_snapshot));
- }
-}
-
-
-#if BX_SUPPORT_VBE
- Bit8u BX_CPP_AttrRegparmN(1)
-bx_vga_c::vbe_mem_read(Bit32u addr)
-{
- Bit32u offset;
-
- if (addr >= VBE_DISPI_LFB_PHYSICAL_ADDRESS)
- {
- // LFB read
- offset = addr - VBE_DISPI_LFB_PHYSICAL_ADDRESS;
- }
- else
- {
- // banked mode read
- offset = BX_VGA_THIS s.vbe_bank*65536 + addr - 0xA0000;
- }
-
- // check for out of memory read
- if (offset > VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES)
- return 0;
-
- return (BX_VGA_THIS s.vbe_memory[offset]);
-}
-
- void BX_CPP_AttrRegparmN(2)
-bx_vga_c::vbe_mem_write(Bit32u addr, Bit8u value)
-{
- Bit32u offset;
- unsigned x_tileno, y_tileno;
-
- if (BX_VGA_THIS s.vbe_lfb_enabled)
- {
- if (addr >= VBE_DISPI_LFB_PHYSICAL_ADDRESS)
- {
- // LFB write
- offset = addr - VBE_DISPI_LFB_PHYSICAL_ADDRESS;
- }
- else
- {
- // banked mode write while in LFB mode -> ignore
- return;
- }
- }
- else
- {
- if (addr < VBE_DISPI_LFB_PHYSICAL_ADDRESS)
- {
- // banked mode write
- offset = (BX_VGA_THIS s.vbe_bank*65536) + (addr - 0xA0000);
- }
- else
- {
- // LFB write while in banked mode -> ignore
- return;
- }
- }
-
- // check for out of memory write
- if (offset < VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES)
- {
- BX_VGA_THIS s.vbe_memory[offset]=value;
- }
- else
- {
- // make sure we don't flood the logfile
- static int count=0;
- if (count<100)
- {
- count ++;
- BX_INFO(("VBE_mem_write out of video memory write at %x",offset));
- }
- }
-
- offset-=BX_VGA_THIS s.vbe_virtual_start;
-
- // only update the UI when writing 'onscreen'
- if (offset < BX_VGA_THIS s.vbe_visable_screen_size)
- {
- y_tileno = ((offset / BX_VGA_THIS s.vbe_bpp_multiplier) / BX_VGA_THIS s.vbe_virtual_xres) / Y_TILESIZE;
- x_tileno = ((offset / BX_VGA_THIS s.vbe_bpp_multiplier) % BX_VGA_THIS s.vbe_virtual_xres) / X_TILESIZE;
-
- if ((y_tileno < BX_NUM_Y_TILES) && (x_tileno < BX_NUM_X_TILES))
- {
- BX_VGA_THIS s.vga_mem_updated = 1;
- SET_TILE_UPDATED (x_tileno, y_tileno, 1);
- }
- }
-}
-
- Bit32u
-bx_vga_c::vbe_read_handler(void *this_ptr, Bit32u address, unsigned io_len)
-{
-#if !BX_USE_VGA_SMF
- bx_vga_c *class_ptr = (bx_vga_c *) this_ptr;
-
- return( class_ptr->vbe_read(address, io_len) );
-}
-
-
- Bit32u
-bx_vga_c::vbe_read(Bit32u address, unsigned io_len)
-{
-#else
- UNUSED(this_ptr);
-#endif // !BX_USE_VGA_SMF
-
-// BX_INFO(("VBE_read %x (len %x)", address, io_len));
-
- if ((address==VBE_DISPI_IOPORT_INDEX) ||
- (address==VBE_DISPI_IOPORT_INDEX_OLD))
- {
- // index register
- return (Bit32u) BX_VGA_THIS s.vbe_curindex;
- }
- else
- {
- // data register read
-
- switch (BX_VGA_THIS s.vbe_curindex)
- {
- case VBE_DISPI_INDEX_ID: // Display Interface ID check
- {
- return BX_VGA_THIS s.vbe_cur_dispi;
- } break;
-
- case VBE_DISPI_INDEX_XRES: // x resolution
- {
- return BX_VGA_THIS s.vbe_xres;
- } break;
-
- case VBE_DISPI_INDEX_YRES: // y resolution
- {
- return BX_VGA_THIS s.vbe_yres;
- } break;
-
- case VBE_DISPI_INDEX_BPP: // bpp
- {
- return BX_VGA_THIS s.vbe_bpp;
- } break;
-
- case VBE_DISPI_INDEX_ENABLE: // vbe enabled
- {
- return BX_VGA_THIS s.vbe_enabled;
- } break;
-
- case VBE_DISPI_INDEX_BANK: // current bank
- {
- return BX_VGA_THIS s.vbe_bank;
- } break;
-
- case VBE_DISPI_INDEX_X_OFFSET:
- {
- return BX_VGA_THIS s.vbe_offset_x;
- } break;
-
- case VBE_DISPI_INDEX_Y_OFFSET:
- {
- return BX_VGA_THIS s.vbe_offset_y;
- } break;
-
- case VBE_DISPI_INDEX_VIRT_WIDTH:
- {
- return BX_VGA_THIS s.vbe_virtual_xres;
-
- } break;
-
- case VBE_DISPI_INDEX_VIRT_HEIGHT:
- {
- return BX_VGA_THIS s.vbe_virtual_yres;
- } break;
-
-
- default:
- {
- BX_PANIC(("VBE unknown data read index 0x%x",BX_VGA_THIS s.vbe_curindex));
- } break;
- }
- }
- BX_PANIC(("VBE_read shouldn't reach this"));
- return 0; /* keep compiler happy */
-}
-
- void
-bx_vga_c::vbe_write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len)
-{
-#if !BX_USE_VGA_SMF
- bx_vga_c *class_ptr = (bx_vga_c *) this_ptr;
-
- class_ptr->vbe_write(address, value, io_len);
-}
-
- Bit32u
-bx_vga_c::vbe_write(Bit32u address, Bit32u value, unsigned io_len)
-{
-#else
- UNUSED(this_ptr);
-#endif
-
-// BX_INFO(("VBE_write %x = %x (len %x)", address, value, io_len));
-
- switch(address)
- {
- // index register
- case VBE_DISPI_IOPORT_INDEX:
- // legacy index register
- case VBE_DISPI_IOPORT_INDEX_OLD:
-
- BX_VGA_THIS s.vbe_curindex = (Bit16u) value;
- break;
-
- // data register
- // FIXME: maybe do some 'sanity' checks on received data?
- case VBE_DISPI_IOPORT_DATA:
- // legacy data register
- case VBE_DISPI_IOPORT_DATA_OLD:
- switch (BX_VGA_THIS s.vbe_curindex)
- {
- case VBE_DISPI_INDEX_ID: // Display Interface ID check
- {
- if ( (value == VBE_DISPI_ID0) ||
- (value == VBE_DISPI_ID1) ||
- (value == VBE_DISPI_ID2) )
- {
- // allow backwards compatible with previous dispi bioses
- BX_VGA_THIS s.vbe_cur_dispi=value;
- }
- else
- {
- BX_PANIC(("VBE unknown Display Interface %x",value));
- }
-
- // make sure we don't flood the logfile
- static int count=0;
- if (count < 100)
- {
- count++;
- BX_INFO(("VBE known Display Interface %x",value));
- }
- } break;
-
- case VBE_DISPI_INDEX_XRES: // set xres
- {
- // check that we don't set xres during vbe enabled
- if (!BX_VGA_THIS s.vbe_enabled)
- {
- // check for within max xres range
- if (value <= VBE_DISPI_MAX_XRES)
- {
- BX_VGA_THIS s.vbe_xres=(Bit16u) value;
- BX_INFO(("VBE set xres (%d)",value));
- }
- else
- {
- BX_INFO(("VBE set xres more then max xres (%d)",value));
- }
- }
- else
- {
- BX_INFO(("VBE set xres during vbe enabled!"));
- }
- } break;
-
- case VBE_DISPI_INDEX_YRES: // set yres
- {
- // check that we don't set yres during vbe enabled
- if (!BX_VGA_THIS s.vbe_enabled)
- {
- // check for within max yres range
- if (value <= VBE_DISPI_MAX_YRES)
- {
- BX_VGA_THIS s.vbe_yres=(Bit16u) value;
- BX_INFO(("VBE set yres (%d)",value));
- }
- else
- {
- BX_INFO(("VBE set yres more then max yres (%d)",value));
- }
- }
- else
- {
- BX_INFO(("VBE set yres during vbe enabled!"));
- }
- } break;
-
- case VBE_DISPI_INDEX_BPP: // set bpp
- {
- // check that we don't set bpp during vbe enabled
- if (!BX_VGA_THIS s.vbe_enabled)
- {
- // for backward compatiblity
- if (value == 0) value = VBE_DISPI_BPP_8;
- // check for correct bpp range
- if ((value == VBE_DISPI_BPP_4) || (value == VBE_DISPI_BPP_8) || (value == VBE_DISPI_BPP_15) ||
- (value == VBE_DISPI_BPP_16) || (value == VBE_DISPI_BPP_24) || (value == VBE_DISPI_BPP_32))
- {
- BX_VGA_THIS s.vbe_bpp=(Bit16u) value;
- BX_INFO(("VBE set bpp (%d)",value));
- }
- else
- {
- BX_INFO(("VBE set bpp with unknown bpp (%d)",value));
- }
- }
- else
- {
- BX_INFO(("VBE set bpp during vbe enabled!"));
- }
- } break;
-
- case VBE_DISPI_INDEX_BANK: // set bank
- {
- value=value & 0xff ; // FIXME lobyte = vbe bank A?
-
- // check for max bank nr
- if (value < (VBE_DISPI_TOTAL_VIDEO_MEMORY_KB /64))
- {
- if (!BX_VGA_THIS s.vbe_lfb_enabled)
- {
- BX_DEBUG(("VBE set bank to %d", value));
- BX_VGA_THIS s.vbe_bank=value;
- }
- else
- {
- BX_ERROR(("VBE set bank in LFB mode ignored"));
- }
- }
- else
- {
- BX_INFO(("VBE set invalid bank (%d)",value));
- }
- } break;
-
- case VBE_DISPI_INDEX_ENABLE: // enable video
- {
- if (value & VBE_DISPI_ENABLED)
- {
- unsigned depth=0;
-
- // setup virtual resolution to be the same as current reso
- BX_VGA_THIS s.vbe_virtual_yres=BX_VGA_THIS s.vbe_yres;
- BX_VGA_THIS s.vbe_virtual_xres=BX_VGA_THIS s.vbe_xres;
-
- // reset offset
- BX_VGA_THIS s.vbe_offset_x=0;
- BX_VGA_THIS s.vbe_offset_y=0;
- BX_VGA_THIS s.vbe_virtual_start=0;
-
- switch((BX_VGA_THIS s.vbe_bpp))
- {
- // Default pixel sizes
- case VBE_DISPI_BPP_8:
- BX_VGA_THIS s.vbe_bpp_multiplier = 1;
- BX_VGA_THIS s.vbe_line_byte_width = BX_VGA_THIS s.vbe_virtual_xres;
- BX_VGA_THIS s.vbe_visable_screen_size = ((BX_VGA_THIS s.vbe_xres) * (BX_VGA_THIS s.vbe_yres));
- depth=8;
- break;
-
- case VBE_DISPI_BPP_4:
- BX_VGA_THIS s.vbe_bpp_multiplier = 1;
- BX_VGA_THIS s.vbe_line_byte_width = BX_VGA_THIS s.vbe_virtual_xres;
- BX_VGA_THIS s.vbe_visable_screen_size = ((BX_VGA_THIS s.vbe_xres) * (BX_VGA_THIS s.vbe_yres));
- depth=4;
- break;
-
- case VBE_DISPI_BPP_15:
- BX_VGA_THIS s.vbe_bpp_multiplier = 2;
- BX_VGA_THIS s.vbe_line_byte_width = BX_VGA_THIS s.vbe_virtual_xres * 2;
- BX_VGA_THIS s.vbe_visable_screen_size = ((BX_VGA_THIS s.vbe_xres) * (BX_VGA_THIS s.vbe_yres)) * 2;
- depth=15;
- break;
-
- case VBE_DISPI_BPP_16:
- BX_VGA_THIS s.vbe_bpp_multiplier = 2;
- BX_VGA_THIS s.vbe_line_byte_width = BX_VGA_THIS s.vbe_virtual_xres * 2;
- BX_VGA_THIS s.vbe_visable_screen_size = ((BX_VGA_THIS s.vbe_xres) * (BX_VGA_THIS s.vbe_yres)) * 2;
- depth=16;
- break;
-
- case VBE_DISPI_BPP_24:
- BX_VGA_THIS s.vbe_bpp_multiplier = 3;
- BX_VGA_THIS s.vbe_line_byte_width = BX_VGA_THIS s.vbe_virtual_xres * 3;
- BX_VGA_THIS s.vbe_visable_screen_size = ((BX_VGA_THIS s.vbe_xres) * (BX_VGA_THIS s.vbe_yres)) * 3;
- depth=24;
- break;
-
- case VBE_DISPI_BPP_32:
- BX_VGA_THIS s.vbe_bpp_multiplier = 4;
- BX_VGA_THIS s.vbe_line_byte_width = BX_VGA_THIS s.vbe_virtual_xres << 2;
- BX_VGA_THIS s.vbe_visable_screen_size = ((BX_VGA_THIS s.vbe_xres) * (BX_VGA_THIS s.vbe_yres)) << 2;
- depth=32;
- break;
- }
-
- BX_INFO(("VBE enabling x %d, y %d, bpp %d, %u bytes visible", BX_VGA_THIS s.vbe_xres, BX_VGA_THIS s.vbe_yres, BX_VGA_THIS s.vbe_bpp, BX_VGA_THIS s.vbe_visable_screen_size));
-
- if (depth > 4)
- {
- BX_VGA_THIS s.vbe_lfb_enabled=(bx_bool)(value & VBE_DISPI_LFB_ENABLED);
- if ((value & VBE_DISPI_NOCLEARMEM) == 0)
- {
- memset(BX_VGA_THIS s.vbe_memory, 0, BX_VGA_THIS s.vbe_visable_screen_size);
- }
- bx_gui->dimension_update(BX_VGA_THIS s.vbe_xres, BX_VGA_THIS s.vbe_yres, 0, 0, depth);
- old_BPP = depth;
- // some test applications expect these standard VGA settings
- BX_VGA_THIS s.CRTC.reg[9] = 0x00;
- BX_VGA_THIS s.attribute_ctrl.mode_ctrl.graphics_alpha = 1;
- BX_VGA_THIS s.graphics_ctrl.memory_mapping = 1;
- BX_VGA_THIS s.CRTC.reg[1] = (BX_VGA_THIS s.vbe_xres / 8) - 1;
- BX_VGA_THIS s.CRTC.reg[19] = BX_VGA_THIS s.vbe_xres >> 2;
- BX_VGA_THIS s.attribute_ctrl.mode_ctrl.pixel_clock_select = 1;
- BX_VGA_THIS s.CRTC.reg[18] = (BX_VGA_THIS s.vbe_yres - 1) & 0xff;
- BX_VGA_THIS s.CRTC.reg[7] &= ~0x42;
- if ((BX_VGA_THIS s.vbe_yres - 1) & 0x0100) {
- BX_VGA_THIS s.CRTC.reg[7] |= 0x02;
- }
- if ((BX_VGA_THIS s.vbe_yres - 1) & 0x0200) {
- BX_VGA_THIS s.CRTC.reg[7] |= 0x40;
- }
- }
- }
- else
- {
- if (BX_VGA_THIS s.vbe_enabled) BX_INFO(("VBE disabling"));
- BX_VGA_THIS s.vbe_lfb_enabled=0;
- }
- BX_VGA_THIS s.vbe_enabled=(bx_bool)(value & VBE_DISPI_ENABLED);
- } break;
-
- case VBE_DISPI_INDEX_X_OFFSET:
- {
- // BX_INFO(("VBE offset x %x",value));
- BX_VGA_THIS s.vbe_offset_x=(Bit16u)value;
-
- BX_VGA_THIS s.vbe_virtual_start = ((BX_VGA_THIS s.vbe_offset_y) * (BX_VGA_THIS s.vbe_line_byte_width)) +
- ((BX_VGA_THIS s.vbe_offset_x) * (BX_VGA_THIS s.vbe_bpp_multiplier));
-
- BX_VGA_THIS s.vga_mem_updated = 1;
- for (unsigned xti = 0; xti < BX_NUM_X_TILES; xti++) {
- for (unsigned yti = 0; yti < BX_NUM_Y_TILES; yti++) {
- SET_TILE_UPDATED (xti, yti, 1);
- }
- }
- } break;
-
- case VBE_DISPI_INDEX_Y_OFFSET:
- {
- // BX_INFO(("VBE offset y %x",value));
- BX_VGA_THIS s.vbe_offset_y=(Bit16u)value;
- BX_VGA_THIS s.vbe_virtual_start = ((BX_VGA_THIS s.vbe_offset_y) * (BX_VGA_THIS s.vbe_line_byte_width)) +
- ((BX_VGA_THIS s.vbe_offset_x) * (BX_VGA_THIS s.vbe_bpp_multiplier));
-
- BX_VGA_THIS s.vga_mem_updated = 1;
- for (unsigned xti = 0; xti < BX_NUM_X_TILES; xti++) {
- for (unsigned yti = 0; yti < BX_NUM_Y_TILES; yti++) {
- SET_TILE_UPDATED (xti, yti, 1);
- }
- }
- } break;
-
- case VBE_DISPI_INDEX_VIRT_WIDTH:
- {
- BX_INFO(("VBE requested virtual width %d",value));
-
- // calculate virtual width & height dimensions
- // req:
- // virt_width > xres
- // virt_height >=yres
- // virt_width*virt_height < MAX_VIDEO_MEMORY
-
- // basicly 2 situations
-
- // situation 1:
- // MAX_VIDEO_MEMORY / virt_width >= yres
- // adjust result height
- // else
- // adjust result width based upon virt_height=yres
- Bit16u new_width=value;
- Bit16u new_height=(sizeof(BX_VGA_THIS s.vbe_memory) / BX_VGA_THIS s.vbe_bpp_multiplier) / new_width;
- if (new_height >=BX_VGA_THIS s.vbe_yres)
- {
- // we have a decent virtual width & new_height
- BX_INFO(("VBE decent virtual height %d",new_height));
- }
- else
- {
- // no decent virtual height: adjust width & height
- new_height=BX_VGA_THIS s.vbe_yres;
- new_width=(sizeof(BX_VGA_THIS s.vbe_memory) / BX_VGA_THIS s.vbe_bpp_multiplier) / new_height;
-
- BX_INFO(("VBE recalc virtual width %d height %d",new_width, new_height));
- }
-
- BX_VGA_THIS s.vbe_virtual_xres=new_width;
- BX_VGA_THIS s.vbe_virtual_yres=new_height;
- BX_VGA_THIS s.vbe_visable_screen_size = (new_width * (BX_VGA_THIS s.vbe_yres)) * BX_VGA_THIS s.vbe_bpp_multiplier;
-
- } break;
- /*
- case VBE_DISPI_INDEX_VIRT_HEIGHT:
- {
- BX_INFO(("VBE virtual height %x",value));
-
- } break;
- */
- default:
- {
- BX_PANIC(("VBE unknown data write index 0x%x",BX_VGA_THIS s.vbe_curindex));
- } break;
- }
- break;
-
- } // end switch address
-}
-
-#endif
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: vga.h,v 1.36 2003/12/31 10:33:27 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-#if BX_SUPPORT_VBE
- #define VBE_DISPI_TOTAL_VIDEO_MEMORY_MB 4
-
- #define VBE_DISPI_BANK_ADDRESS 0xA0000
- #define VBE_DISPI_BANK_SIZE_KB 64
-
- #define VBE_DISPI_MAX_XRES 1024
- #define VBE_DISPI_MAX_YRES 768
-
- #define VBE_DISPI_IOPORT_INDEX 0x01CE
- #define VBE_DISPI_IOPORT_DATA 0x01CF
-
- #define VBE_DISPI_IOPORT_INDEX_OLD 0xFF80
- #define VBE_DISPI_IOPORT_DATA_OLD 0xFF81
-
- #define VBE_DISPI_INDEX_ID 0x0
- #define VBE_DISPI_INDEX_XRES 0x1
- #define VBE_DISPI_INDEX_YRES 0x2
- #define VBE_DISPI_INDEX_BPP 0x3
- #define VBE_DISPI_INDEX_ENABLE 0x4
- #define VBE_DISPI_INDEX_BANK 0x5
- #define VBE_DISPI_INDEX_VIRT_WIDTH 0x6
- #define VBE_DISPI_INDEX_VIRT_HEIGHT 0x7
- #define VBE_DISPI_INDEX_X_OFFSET 0x8
- #define VBE_DISPI_INDEX_Y_OFFSET 0x9
-
- #define VBE_DISPI_ID0 0xB0C0
- #define VBE_DISPI_ID1 0xB0C1
- #define VBE_DISPI_ID2 0xB0C2
-
- #define VBE_DISPI_BPP_4 0x04
- #define VBE_DISPI_BPP_8 0x08
- #define VBE_DISPI_BPP_15 0x0F
- #define VBE_DISPI_BPP_16 0x10
- #define VBE_DISPI_BPP_24 0x18
- #define VBE_DISPI_BPP_32 0x20
-
- #define VBE_DISPI_DISABLED 0x00
- #define VBE_DISPI_ENABLED 0x01
- #define VBE_DISPI_NOCLEARMEM 0x80
- #define VBE_DISPI_LFB_ENABLED 0x40
-
- #define VBE_DISPI_LFB_PHYSICAL_ADDRESS 0xE0000000
-
-
-#define VBE_DISPI_TOTAL_VIDEO_MEMORY_KB (VBE_DISPI_TOTAL_VIDEO_MEMORY_MB * 1024)
-#define VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES (VBE_DISPI_TOTAL_VIDEO_MEMORY_KB * 1024)
-
-#define BX_MAX_XRES VBE_DISPI_MAX_XRES
-#define BX_MAX_YRES VBE_DISPI_MAX_YRES
-
-#else
-
-#define BX_MAX_XRES 800
-#define BX_MAX_YRES 600
-
-#endif //BX_SUPPORT_VBE
-
-#define X_TILESIZE 16
-#define Y_TILESIZE 24
-#define BX_NUM_X_TILES (BX_MAX_XRES /X_TILESIZE)
-#define BX_NUM_Y_TILES (BX_MAX_YRES /Y_TILESIZE)
-
-// Support varying number of rows of text. This used to
-// be limited to only 25 lines.
-#define BX_MAX_TEXT_LINES 100
-
-#if BX_USE_VGA_SMF
-# define BX_VGA_SMF static
-# define BX_VGA_THIS theVga->
-#else
-# define BX_VGA_SMF
-# define BX_VGA_THIS this->
-#endif
-
-
-class bx_vga_c : public bx_vga_stub_c {
-public:
-
- bx_vga_c(void);
- ~bx_vga_c(void);
- virtual void init(void);
- virtual void bios_init(void);
- virtual void reset(unsigned type);
- virtual Bit8u mem_read(Bit32u addr);
- // Note: either leave value of type Bit8u, or mask it when
- // used to 8 bits, in memory.cc
- virtual void mem_write(Bit32u addr, Bit8u value);
- virtual void trigger_timer(void *this_ptr);
-
-#if BX_SUPPORT_VBE
- BX_VGA_SMF Bit8u vbe_mem_read(Bit32u addr) BX_CPP_AttrRegparmN(1);
- BX_VGA_SMF void vbe_mem_write(Bit32u addr, Bit8u value) BX_CPP_AttrRegparmN(2);
-#endif
-
- virtual void redraw_area(unsigned x0, unsigned y0,
- unsigned width, unsigned height);
-
- virtual void set_update_interval (unsigned interval);
- virtual void get_text_snapshot(Bit8u **text_snapshot, unsigned *txHeight,
- unsigned *txWidth);
- virtual Bit8u get_actl_palette_idx(Bit8u index);
-
-private:
-
- static Bit32u read_handler(void *this_ptr, Bit32u address, unsigned io_len);
- static void write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len);
- static void write_handler_no_log(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len);
-
-#if BX_SUPPORT_VBE
- static Bit32u vbe_read_handler(void *this_ptr, Bit32u address, unsigned io_len);
- static void vbe_write_handler(void *this_ptr, Bit32u address, Bit32u value, unsigned io_len);
-#endif
-
- struct {
- struct {
- bx_bool color_emulation; // 1=color emulation, base address = 3Dx
- // 0=mono emulation, base address = 3Bx
- bx_bool enable_ram; // enable CPU access to video memory if set
- Bit8u clock_select; // 0=25Mhz 1=28Mhz
- bx_bool select_high_bank; // when in odd/even modes, select
- // high 64k bank if set
- bx_bool horiz_sync_pol; // bit6: negative if set
- bx_bool vert_sync_pol; // bit7: negative if set
- // bit7,bit6 represent number of lines on display:
- // 0 = reserved
- // 1 = 400 lines
- // 2 = 350 lines
- // 3 - 480 lines
- } misc_output;
-
- struct {
- Bit8u address;
- Bit8u reg[0x19];
- } CRTC;
-
- struct {
- bx_bool flip_flop; /* 0 = address, 1 = data-write */
- unsigned address; /* register number */
- bx_bool video_enabled;
- Bit8u palette_reg[16];
- Bit8u overscan_color;
- Bit8u color_plane_enable;
- Bit8u horiz_pel_panning;
- Bit8u color_select;
- struct {
- bx_bool graphics_alpha;
- bx_bool display_type;
- bx_bool enable_line_graphics;
- bx_bool blink_intensity;
- bx_bool pixel_panning_compat;
- bx_bool pixel_clock_select;
- bx_bool internal_palette_size;
- } mode_ctrl;
- } attribute_ctrl;
-
- struct {
- Bit8u write_data_register;
- Bit8u write_data_cycle; /* 0, 1, 2 */
- Bit8u read_data_register;
- Bit8u read_data_cycle; /* 0, 1, 2 */
- Bit8u dac_state;
- struct {
- Bit8u red;
- Bit8u green;
- Bit8u blue;
- } data[256];
- Bit8u mask;
- } pel;
-
-
- struct {
- Bit8u index;
- Bit8u set_reset;
- Bit8u enable_set_reset;
- Bit8u color_compare;
- Bit8u data_rotate;
- Bit8u raster_op;
- Bit8u read_map_select;
- Bit8u write_mode;
- bx_bool read_mode;
- bx_bool odd_even;
- bx_bool chain_odd_even;
- Bit8u shift_reg;
- bx_bool graphics_alpha;
- Bit8u memory_mapping; /* 0 = use A0000-BFFFF
- * 1 = use A0000-AFFFF EGA/VGA graphics modes
- * 2 = use B0000-B7FFF Monochrome modes
- * 3 = use B8000-BFFFF CGA modes
- */
- Bit8u color_dont_care;
- Bit8u bitmask;
- Bit8u latch[4];
- } graphics_ctrl;
-
- struct {
- Bit8u index;
- Bit8u map_mask;
- bx_bool map_mask_bit[4];
- bx_bool reset1;
- bx_bool reset2;
- Bit8u reg1;
- Bit8u char_map_select;
- bx_bool extended_mem;
- bx_bool odd_even;
- bx_bool chain_four;
- } sequencer;
-
- bx_bool vga_mem_updated;
- unsigned x_tilesize;
- unsigned y_tilesize;
- unsigned line_offset;
- unsigned line_compare;
- unsigned vertical_display_end;
- bx_bool vga_tile_updated[BX_NUM_X_TILES][BX_NUM_Y_TILES];
- Bit8u vga_memory[256 * 1024];
- Bit8u text_snapshot[32 * 1024]; // current text snapshot
- Bit8u rgb[3 * 256];
- Bit8u tile[X_TILESIZE * Y_TILESIZE * 4]; /**< Currently allocates the tile as large as needed. */
- Bit16u charmap_address;
- bx_bool x_dotclockdiv2;
- bx_bool y_doublescan;
-
-#if BX_SUPPORT_VBE
- Bit8u vbe_memory[VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES];
- Bit16u vbe_cur_dispi;
- Bit16u vbe_xres;
- Bit16u vbe_yres;
- Bit16u vbe_bpp;
- Bit16u vbe_bank;
- bx_bool vbe_enabled;
- Bit16u vbe_curindex;
- Bit32u vbe_visable_screen_size; /**< in bytes */
- Bit16u vbe_offset_x; /**< Virtual screen x start (in pixels) */
- Bit16u vbe_offset_y; /**< Virtual screen y start (in pixels) */
- Bit16u vbe_virtual_xres;
- Bit16u vbe_virtual_yres;
- Bit16u vbe_line_byte_width; /**< For dealing with bpp>8, this is they width of a line in bytes. */
- Bit32u vbe_virtual_start; /**< For dealing with bpp>8, this is where the virtual screen starts. */
- Bit8u vbe_bpp_multiplier; /**< We have to save this b/c sometimes we need to recalculate stuff with it. */
- bx_bool vbe_lfb_enabled;
-#endif
- } s; // state information
-
-
-#if !BX_USE_VGA_SMF
- Bit32u read(Bit32u address, unsigned io_len);
- void write(Bit32u address, Bit32u value, unsigned io_len, bx_bool no_log);
-#else
- void write(Bit32u address, Bit32u value, unsigned io_len, bx_bool no_log);
-#endif
-
-#if BX_SUPPORT_VBE
-
-#if !BX_USE_VGA_SMF
- Bit32u vbe_read(Bit32u address, unsigned io_len);
- void vbe_write(Bit32u address, Bit32u value, unsigned io_len, bx_bool no_log);
-#else
- void vbe_write(Bit32u address, Bit32u value, unsigned io_len, bx_bool no_log);
-#endif
-#endif
-
- int timer_id;
-
- public:
- static void timer_handler(void *);
- BX_VGA_SMF void timer(void);
-
- private:
- BX_VGA_SMF void update(void);
- BX_VGA_SMF void dump_status(void);
- BX_VGA_SMF void determine_screen_dimensions(unsigned *piHeight,
- unsigned *piWidth);
- };
+++ /dev/null
-////////////////////////////////////////////////////////////////////////
-// $Id: virt_timer.cc,v 1.19.2.1 2004/02/06 22:14:36 danielg4 Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-/////////////////////////////////////////////////////////////////////////
-//
-//Realtime Algorithm (with gettimeofday)
-// HAVE:
-// Real number of usec.
-// Emulated number of usec.
-// WANT:
-// Number of ticks to use.
-// Number of emulated usec to wait until next try.
-//
-// ticks=number of ticks needed to match total real usec.
-// if(desired ticks > max ticks for elapsed real time)
-// ticks = max ticks for elapsed real time.
-// if(desired ticks > max ticks for elapsed emulated usec)
-// ticks = max ticks for emulated usec.
-// next wait ticks = number of ticks until next event.
-// next wait real usec = (current ticks + next wait ticks) * usec per ticks
-// next wait emulated usec = next wait real usec * emulated usec / real usec
-// if(next wait emulated usec < minimum emulated usec for next wait ticks)
-// next wait emulated usec = minimum emulated usec for next wait ticks.
-// if(next wait emulated usec > max emulated usec wait)
-// next wait emulated usec = max emulated usec wait.
-//
-// How to calculate elapsed real time:
-// store an unused time value whenever no ticks are used in a given time.
-// add this to the current elapsed time.
-// How to calculate elapsed emulated time:
-// same as above.
-// Above can be done by not updating last_usec and last_sec.
-//
-// How to calculate emulated usec/real usec:
-// Each time there are actual ticks:
-// Alpha_product(old emulated usec, emulated usec);
-// Alpha_product(old real usec, real usec);
-// Divide resulting values.
-//
-/////////////////////////////////////////////////////////////////////////
-
-#include "bochs.h"
-
-#define BX_USE_VIRTUAL_TIMERS 1
-#define BX_VIRTUAL_TIMERS_REALTIME 1
-
-//Important constant #defines:
-#define USEC_PER_SECOND (1000000)
-
-
-// define a macro to convert floating point numbers into 64-bit integers.
-// In MSVC++ you can convert a 64-bit float into a 64-bit signed integer,
-// but it will not convert a 64-bit float into a 64-bit unsigned integer.
-// This macro works around that.
-#define F2I(x) ((Bit64u)(Bit64s) (x))
-#define I2F(x) ((double)(Bit64s) (x))
-
-//CONFIGURATION #defines:
-
-
-//MAINLINE Configuration (For realtime PIT):
-
-//How much faster than real time we can go:
-#define MAX_MULT (1.25)
-
-//Minimum number of emulated useconds per second.
-// Now calculated using BX_MIN_IPS, the minimum number of
-// instructions per second.
-#define MIN_USEC_PER_SECOND (((((Bit64u)USEC_PER_SECOND)*((Bit64u)BX_MIN_IPS))/((Bit64u)(bx_options.Oips->get())))+(Bit64u)1)
-
-
-//DEBUG configuration:
-
-//Debug with printf options.
-#define DEBUG_REALTIME_WITH_PRINTF 0
-
-//Use to test execution at multiples of real time.
-#define TIME_DIVIDER (1)
-#define TIME_MULTIPLIER (1)
-#define TIME_HEADSTART (0)
-
-
-#define GET_VIRT_REALTIME64_USEC() (((bx_get_realtime64_usec()*(Bit64u)TIME_MULTIPLIER/(Bit64u)TIME_DIVIDER)))
-//Set up Logging.
-#define LOG_THIS bx_virt_timer.
-
-//A single instance.
-bx_virt_timer_c bx_virt_timer;
-
-
-//Generic MAX and MIN Functions
-#define BX_MAX(a,b) ( ((a)>(b))?(a):(b) )
-#define BX_MIN(a,b) ( ((a)>(b))?(b):(a) )
-
-
-//USEC_ALPHA is multiplier for the past.
-//USEC_ALPHA_B is 1-USEC_ALPHA, or multiplier for the present.
-#define USEC_ALPHA ((double)(.8))
-#define USEC_ALPHA_B ((double)(((double)1)-USEC_ALPHA))
-#define USEC_ALPHA2 ((double)(.5))
-#define USEC_ALPHA2_B ((double)(((double)1)-USEC_ALPHA2))
-#define ALPHA_LOWER(old,new) ((Bit64u)((old<new)?((USEC_ALPHA*(I2F(old)))+(USEC_ALPHA_B*(I2F(new)))):((USEC_ALPHA2*(I2F(old)))+(USEC_ALPHA2_B*(I2F(new))))))
-
-
-//Conversion between emulated useconds and optionally realtime ticks.
-#define TICKS_TO_USEC(a) ( ((a)*usec_per_second)/ticks_per_second )
-#define USEC_TO_TICKS(a) ( ((a)*ticks_per_second)/usec_per_second )
-
-bx_virt_timer_c::bx_virt_timer_c( void )
-{
- put("VTIMER");
- settype(VTIMERLOG);
-
- numTimers = 0;
- current_timers_time = 0;
- timers_next_event_time = BX_MAX_VIRTUAL_TIME;
- last_sequential_time = 0;
- in_timer_handler = 0;
- virtual_next_event_time = BX_MAX_VIRTUAL_TIME;
- current_virtual_time = 0;
-
- use_virtual_timers = BX_USE_VIRTUAL_TIMERS;
- init_done = 0;
-}
-
-bx_virt_timer_c::~bx_virt_timer_c( void )
-{
-}
-
-
-
-const Bit64u bx_virt_timer_c::NullTimerInterval = BX_MAX_VIRTUAL_TIME;
-
-void
-bx_virt_timer_c::nullTimer(void* this_ptr) {
- UNUSED(this_ptr);
-}
-
-void
-bx_virt_timer_c::periodic(Bit64u time_passed) {
- //Assert that we haven't skipped any events.
- BX_ASSERT (time_passed <= timers_next_event_time);
- BX_ASSERT(!in_timer_handler);
-
- //Update time variables.
- timers_next_event_time -= time_passed;
- current_timers_time += time_passed;
-
- //If no events are occurring, just pass the time and we're done.
- if( time_passed < timers_next_event_time ) {
- return;
- }
- //Starting timer handler calls.
- in_timer_handler = 1;
- //Otherwise, cause any events to occur that should.
- unsigned i;
- for(i=0;i<numTimers;i++) {
- if( timer[i].inUse && timer[i].active ) {
- //Assert that we haven't skipped any timers.
- BX_ASSERT(current_timers_time <= timer[i].timeToFire);
- if(timer[i].timeToFire == current_timers_time) {
- if(timer[i].continuous) {
- timer[i].timeToFire+=timer[i].period;
- } else {
- timer[i].active = 0;
- }
- //This function MUST return, or the timer mechanism
- // will be broken.
- timer[i].funct(timer[i].this_ptr);
- }
- }
- }
- //Finished timer handler calls.
- in_timer_handler = 0;
- //Use a second FOR loop so that a timer function call can
- // change the behavior of another timer.
- //timers_next_event_time normally contains a cycle count, not a cycle time.
- // here we use it as a temporary variable that IS a cycle time,
- // but then convert it back to a cycle count afterwards.
- timers_next_event_time = current_timers_time + BX_MAX_VIRTUAL_TIME;
- for(i=0;i<numTimers;i++) {
- if( timer[i].inUse && timer[i].active && ((timer[i].timeToFire)<timers_next_event_time) ) {
- timers_next_event_time = timer[i].timeToFire;
- }
- }
- timers_next_event_time-=current_timers_time;
- next_event_time_update();
- //FIXME
-}
-
-
-//Get the current virtual time.
-// This may return the same value on subsequent calls.
-Bit64u
-bx_virt_timer_c::time_usec(void) {
- if(!use_virtual_timers) {
- return bx_pc_system.time_usec();
- }
-
- //Update the time here only if we're not in a timer handler.
- //If we're in a timer handler we're up-to-date, and otherwise
- // this prevents call stack loops.
- if(!in_timer_handler) {
- timer_handler();
- }
-
- return current_timers_time;
-}
-
-//Get the current virtual time.
-// This will return a monotonically increasing value.
-// MUST NOT be called from within a timer interrupt.
-Bit64u
-bx_virt_timer_c::time_usec_sequential(void) {
- if(!use_virtual_timers) {
- return bx_pc_system.time_usec_sequential();
- }
-
- //Can't prevent call stack loops here, so this
- // MUST NOT be called from within a timer handler.
- BX_ASSERT(timers_next_event_time>0);
- BX_ASSERT(!in_timer_handler);
-
- if(last_sequential_time >= current_timers_time) {
- periodic(1);
- last_sequential_time = current_timers_time;
- }
- return current_timers_time;
-}
-
-
-
-//Register a timer handler to go off after a given interval.
-//Register a timer handler to go off with a periodic interval.
-int
-bx_virt_timer_c::register_timer( void *this_ptr, bx_timer_handler_t handler,
- Bit32u useconds,
- bx_bool continuous, bx_bool active,
- const char *id) {
- if(!use_virtual_timers) {
- return bx_pc_system.register_timer(this_ptr, handler, useconds,
- continuous, active, id);
- }
-
- //We don't like starting with a zero period timer.
- BX_ASSERT((!active) || (useconds>0));
-
- //Search for an unused timer.
- unsigned int i;
- for (i=0; i < numTimers; i++) {
- if (timer[i].inUse == 0 || i==numTimers)
- break;
- }
- // If we didn't find a free slot, increment the bound, numTimers.
- if (i==numTimers)
- numTimers++; // One new timer installed.
- BX_ASSERT(numTimers<BX_MAX_VIRTUAL_TIMERS);
-
- timer[i].inUse = 1;
- timer[i].period = useconds;
- timer[i].timeToFire = current_timers_time + (Bit64u)useconds;
- timer[i].active = active;
- timer[i].continuous = continuous;
- timer[i].funct = handler;
- timer[i].this_ptr = this_ptr;
- strncpy(timer[i].id, id, BxMaxTimerIDLen);
- timer[i].id[BxMaxTimerIDLen-1]=0; //I like null terminated strings.
-
- if(useconds < timers_next_event_time) {
- timers_next_event_time = useconds;
- next_event_time_update();
- //FIXME
- }
- return i;
-}
-
-//unregister a previously registered timer.
-unsigned
-bx_virt_timer_c::unregisterTimer(int timerID) {
- if(!use_virtual_timers) {
- return bx_pc_system.unregisterTimer(timerID);
- }
-
- BX_ASSERT(timerID >= 0);
- BX_ASSERT(timerID < BX_MAX_VIRTUAL_TIMERS);
-
- if (timer[timerID].active) {
- BX_PANIC(("unregisterTimer: timer '%s' is still active!", timer[timerID].id));
- return(0); // Fail.
- }
-
-
- //No need to prevent doing this to unused timers.
- timer[timerID].inUse = 0;
- return(1);
-}
-
-void
-bx_virt_timer_c::start_timers(void) {
- if(!use_virtual_timers) {
- bx_pc_system.start_timers();
- return;
- }
- //FIXME
-}
-
-//activate a deactivated but registered timer.
-void
-bx_virt_timer_c::activate_timer( unsigned timer_index, Bit32u useconds,
- bx_bool continuous ) {
- if(!use_virtual_timers) {
- bx_pc_system.activate_timer(timer_index, useconds, continuous);
- return;
- }
-
- BX_ASSERT(timer_index >= 0);
- BX_ASSERT(timer_index < BX_MAX_VIRTUAL_TIMERS);
-
- BX_ASSERT(timer[timer_index].inUse);
- BX_ASSERT(useconds>0);
-
- timer[timer_index].period=useconds;
- timer[timer_index].timeToFire = current_timers_time + (Bit64u)useconds;
- timer[timer_index].active=1;
- timer[timer_index].continuous=continuous;
-
- if(useconds < timers_next_event_time) {
- timers_next_event_time = useconds;
- next_event_time_update();
- //FIXME
- }
-}
-
-//deactivate (but don't unregister) a currently registered timer.
-void
-bx_virt_timer_c::deactivate_timer( unsigned timer_index ) {
- if(!use_virtual_timers) {
- bx_pc_system.deactivate_timer(timer_index);
- return;
- }
-
- BX_ASSERT(timer_index >= 0);
- BX_ASSERT(timer_index < BX_MAX_VIRTUAL_TIMERS);
-
- //No need to prevent doing this to unused/inactive timers.
- timer[timer_index].active = 0;
-}
-
-void
-bx_virt_timer_c::advance_virtual_time(Bit64u time_passed) {
- BX_ASSERT(time_passed <= virtual_next_event_time);
-
- current_virtual_time += time_passed;
- virtual_next_event_time -= time_passed;
-
- if(current_virtual_time > current_timers_time) {
- periodic(current_virtual_time - current_timers_time);
- }
-}
-
-//Called when next_event_time changes.
-void
-bx_virt_timer_c::next_event_time_update(void) {
- virtual_next_event_time = timers_next_event_time + current_timers_time - current_virtual_time;
- if(init_done) {
- bx_pc_system.deactivate_timer(system_timer_id);
- BX_ASSERT(virtual_next_event_time);
- bx_pc_system.activate_timer(system_timer_id,
- (Bit32u)BX_MIN(0x7FFFFFFF,BX_MAX(1,TICKS_TO_USEC(virtual_next_event_time))),
- 0);
- }
-}
-
-void
-bx_virt_timer_c::init(void) {
-
- if ( (bx_options.clock.Osync->get ()!=BX_CLOCK_SYNC_REALTIME)
- && (bx_options.clock.Osync->get ()!=BX_CLOCK_SYNC_BOTH) )
- virtual_timers_realtime = 0;
- else
- virtual_timers_realtime = 1;
-
- if (virtual_timers_realtime) {
- BX_INFO(("using 'realtime pit' synchronization method"));
- }
-
- register_timer(this, nullTimer, (Bit32u)NullTimerInterval, 1, 1, "Null Timer");
-
- system_timer_id = bx_pc_system.register_timer(this, pc_system_timer_handler,virtual_next_event_time , 0, 1, "Virtual Timer");
-
- //Real time variables:
-#if BX_HAVE_REALTIME_USEC
- last_real_time=GET_VIRT_REALTIME64_USEC()+(Bit64u)TIME_HEADSTART*(Bit64u)USEC_PER_SECOND;
-#endif
- total_real_usec=0;
- last_realtime_delta=0;
- //System time variables:
- last_usec = 0
-;
- usec_per_second = USEC_PER_SECOND;
- stored_delta=0;
- last_system_usec=0;
- em_last_realtime=0;
- //Virtual timer variables:
- total_ticks=0;
- last_realtime_ticks=0;
- ticks_per_second = USEC_PER_SECOND;
-
- init_done = 1;
-}
-
-void
-bx_virt_timer_c::timer_handler(void) {
- if(!virtual_timers_realtime) {
- Bit64u temp_final_time = bx_pc_system.time_usec();
- temp_final_time-=current_virtual_time;
- while(temp_final_time) {
- if((temp_final_time)>(virtual_next_event_time)) {
- temp_final_time-=virtual_next_event_time;
- advance_virtual_time(virtual_next_event_time);
- } else {
- advance_virtual_time(temp_final_time);
- temp_final_time-=temp_final_time;
- }
- }
- bx_pc_system.activate_timer(system_timer_id,
- (Bit32u)BX_MIN(0x7FFFFFFF,(virtual_next_event_time>2)?(virtual_next_event_time-2):1),
- 0);
- return;
- }
-
- Bit64u usec_delta = bx_pc_system.time_usec()-last_usec;
-
- if (usec_delta) {
-#if BX_HAVE_REALTIME_USEC
- Bit64u ticks_delta = 0;
- Bit64u real_time_delta = GET_VIRT_REALTIME64_USEC() - last_real_time;
- Bit64u real_time_total = real_time_delta + total_real_usec;
- Bit64u system_time_delta = (Bit64u)usec_delta + (Bit64u)stored_delta;
- if(real_time_delta) {
- last_realtime_delta = real_time_delta;
- last_realtime_ticks = total_ticks;
- }
- ticks_per_second = USEC_PER_SECOND;
-
- //Start out with the number of ticks we would like
- // to have to line up with real time.
- ticks_delta = real_time_total - total_ticks;
- if(real_time_total < total_ticks) {
- //This slows us down if we're already ahead.
- // probably only an issue on startup, but it solves some problems.
- ticks_delta = 0;
- }
- if(ticks_delta + total_ticks - last_realtime_ticks > (F2I(MAX_MULT * I2F(last_realtime_delta)))) {
- //This keeps us from going too fast in relation to real time.
-#if 0
- ticks_delta = (F2I(MAX_MULT * I2F(last_realtime_delta))) + last_realtime_ticks - total_ticks;
-#endif
- ticks_per_second = F2I(MAX_MULT * I2F(USEC_PER_SECOND));
- }
- if(ticks_delta > system_time_delta * USEC_PER_SECOND / MIN_USEC_PER_SECOND) {
- //This keeps us from having too few instructions between ticks.
- ticks_delta = system_time_delta * USEC_PER_SECOND / MIN_USEC_PER_SECOND;
- }
- if(ticks_delta > virtual_next_event_time) {
- //This keeps us from missing ticks.
- ticks_delta = virtual_next_event_time;
- }
-
- if(ticks_delta) {
-
-# if DEBUG_REALTIME_WITH_PRINTF
- //Every second print some info.
- if(((last_real_time + real_time_delta) / USEC_PER_SECOND) > (last_real_time / USEC_PER_SECOND)) {
- Bit64u temp1, temp2, temp3, temp4;
- temp1 = (Bit64u) total_real_usec;
- temp2 = (total_real_usec);
- temp3 = (Bit64u)total_ticks;
- temp4 = (Bit64u)((total_real_usec) - total_ticks);
- printf("useconds: %llu, ",temp1);
- printf("expect ticks: %llu, ",temp2);
- printf("ticks: %llu, ",temp3);
- printf("diff: %llu\n",temp4);
- }
-# endif
-
- last_real_time += real_time_delta;
- total_real_usec += real_time_delta;
- last_system_usec += system_time_delta;
- stored_delta = 0;
- total_ticks += ticks_delta;
- } else {
- stored_delta = system_time_delta;
- }
-
-
- Bit64u a,b;
- a=(usec_per_second);
- if(real_time_delta) {
- //FIXME
- Bit64u em_realtime_delta = last_system_usec + stored_delta - em_last_realtime;
- b=((Bit64u)USEC_PER_SECOND * em_realtime_delta / real_time_delta);
- em_last_realtime = last_system_usec + stored_delta;
- } else {
- b=a;
- }
- usec_per_second = ALPHA_LOWER(a,b);
-#else
- BX_ASSERT(0);
-#endif
-#if BX_HAVE_REALTIME_USEC
- advance_virtual_time(ticks_delta);
-#endif
- }
-
- last_usec=last_usec + usec_delta;
- bx_pc_system.deactivate_timer(system_timer_id);
- BX_ASSERT(virtual_next_event_time);
- bx_pc_system.activate_timer(system_timer_id,
- (Bit32u)BX_MIN(0x7FFFFFFF,BX_MAX(1,TICKS_TO_USEC(virtual_next_event_time))),
- 0);
-
-}
-
-void
-bx_virt_timer_c::pc_system_timer_handler(void* this_ptr) {
- ((bx_virt_timer_c *)this_ptr)->timer_handler();
-}
-
+++ /dev/null
-
-#ifndef _BX_VIRT_TIMER_H
-#define _BX_VIRT_TIMER_H
-
-
-#define BX_MAX_VIRTUAL_TIMERS (15+BX_SMP_PROCESSORS)
-#define BX_NULL_VIRTUAL_TIMER_HANDLE 10000
-
-#define BX_MAX_VIRTUAL_TIME (0x7fffffff)
-
-class bx_virt_timer_c : public logfunctions {
- private:
-
- struct {
- bx_bool inUse; // Timer slot is in-use (currently registered).
- Bit64u period; // Timer periodocity in virtual useconds.
- Bit64u timeToFire; // Time to fire next (in virtual useconds).
- bx_bool active; // 0=inactive, 1=active.
- bx_bool continuous; // 0=one-shot timer, 1=continuous periodicity.
- bx_timer_handler_t funct; // A callback function for when the
- // timer fires.
- // This function MUST return.
- void *this_ptr; // The this-> pointer for C++ callbacks
- // has to be stored as well.
- char id[BxMaxTimerIDLen]; // String ID of timer.
- } timer[BX_MAX_VIRTUAL_TIMERS];
-
- unsigned numTimers; // Number of currently allocated timers.
-
- //Variables for the timer subsystem:
- Bit64u current_timers_time;
- Bit64u timers_next_event_time;
-
- Bit64u last_sequential_time;
- bx_bool in_timer_handler;
-
- //Variables for the time sync subsystem:
- Bit64u virtual_next_event_time;
- Bit64u current_virtual_time;
-
- //Real time variables:
- Bit64u last_real_time;
- Bit64u total_real_usec;
- Bit64u last_realtime_delta;
- //System time variables:
- Bit64u last_usec;
- Bit64u usec_per_second;
- Bit64u stored_delta;
- Bit64u last_system_usec;
- Bit64u em_last_realtime;
- //Virtual timer variables:
- Bit64u total_ticks;
- Bit64u last_realtime_ticks;
- Bit64u ticks_per_second;
-
- bx_bool init_done;
-
- int system_timer_id;
-
- //Whether or not to use virtual timers.
- bx_bool use_virtual_timers;
- bx_bool virtual_timers_realtime;
-
- // A special null timer is always inserted in the timer[0] slot. This
- // make sure that at least one timer is always active, and that the
- // duration is always less than a maximum 32-bit integer, so a 32-bit
- // counter can be used for the current countdown.
- static const Bit64u NullTimerInterval;
- static void nullTimer(void* this_ptr);
-
-
- //Step the given number of cycles, optionally calling any timer handlers.
- void periodic(Bit64u time_passed);
-
-
- //Called when next_event_time changes.
- void next_event_time_update(void);
-
- //Called to advance the virtual time.
- // calls periodic as needed.
- void advance_virtual_time(Bit64u time_passed);
-
- public:
-
-
- //Get the current virtual time.
- // This may return the same value on subsequent calls.
- Bit64u time_usec(void);
-
- //Get the current virtual time.
- // This will return a monotonically increasing value.
- // MUST NOT be called from within a timer handler.
- Bit64u time_usec_sequential(void);
-
- //Register a timer handler to go off after a given interval.
- //Register a timer handler to go off with a periodic interval.
- int register_timer( void *this_ptr, bx_timer_handler_t handler,
- Bit32u useconds,
- bx_bool continuous, bx_bool active, const char *id);
-
- //unregister a previously registered timer.
- unsigned unregisterTimer(int timerID);
-
- void start_timers(void);
-
- //activate a deactivated but registered timer.
- void activate_timer( unsigned timer_index, Bit32u useconds,
- bx_bool continuous );
-
- //deactivate (but don't unregister) a currently registered timer.
- void deactivate_timer( unsigned timer_index );
-
-
- //Timer handler passed to pc_system
- static void pc_system_timer_handler(void* this_ptr);
-
- //The real timer handler.
- void timer_handler();
-
- //Initialization
- void init(void);
- bx_virt_timer_c(void);
- ~bx_virt_timer_c(void);
-
-};
-
-
-
-extern bx_virt_timer_c bx_virt_timer;
-
-#endif // _BX_VIRT_TIMER_H
--- /dev/null
+/*
+ * QEMU keylayout reader: read rdesktop style keylaouts
+ *
+ * Copyright (c) 2004,2005 Johannes E. Schindelin
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include <ctype.h>
+
+#ifdef KEYBOARD_IGNORE_CASE
+#define STRCMP strcasecmp
+#else
+#define STRCMP strcmp
+#endif
+
+/* binary search through nameToKeysym */
+static int get_keysym(const char* name)
+{
+ int i1=-1,i2=sizeof(name2keysym)/sizeof(name2keysym_t),i3=i2/2,r;
+ while((r=STRCMP(name,name2keysym[i3].name))!=0) {
+ if(r<0)
+ i2=i3;
+ else
+ i1=i3;
+ i3=(i1+i2)/2;
+ if(i2-i1<2)
+ return 0;
+ }
+ return name2keysym[i3].keysym;
+}
+
+typedef unsigned short WORD;
+#define MAX_NORMAL_KEYCODE 512
+#define MAX_EXTRA_COUNT 256
+typedef struct {
+ WORD keysym2keycode[MAX_NORMAL_KEYCODE];
+ struct {
+ int keysym;
+ WORD keycode;
+ } keysym2keycode_extra[MAX_EXTRA_COUNT];
+ int extra_count;
+} kbd_layout_t;
+
+static int parse_int(const char* text)
+{
+ if(!strncmp(text,"0x",2)) {
+ int result=0;
+ sscanf(text+2,"%x",&result);
+ return result;
+ }
+ return atoi(text);
+}
+
+static kbd_layout_t* parse_keyboard_layout(const char* language,kbd_layout_t* k)
+{
+ FILE* f;
+ const char* prefix="/keymaps/";
+ char* file_name=malloc(strlen(prefix)+strlen(language)+strlen(bios_dir)+1);
+
+ if(!k)
+ k=calloc(sizeof(kbd_layout_t),1);
+ strcpy(file_name,bios_dir);
+ strcat(file_name,prefix);
+ strcat(file_name,language);
+ if(file_name[strlen(file_name)-1]=='\n')
+ file_name[strlen(file_name)-1]=0;
+ if(!(f=fopen(file_name,"r"))) {
+ term_printf("Warning: could not read keymap - falling back native keycodes!\n");
+ free(file_name);
+ return 0;
+ }
+ free(file_name);
+ while(!feof(f)) {
+ char line[1024];
+ fgets(line,1024,f);
+ if(line[0]=='#')
+ continue;
+ if(!strncmp(line,"map ",4))
+ continue;
+ if(!strncmp(line,"include ",8))
+ parse_keyboard_layout(line+8,k);
+ else {
+ char* end_of_keysym=line;
+ while(*end_of_keysym!=0 && *end_of_keysym!=' ')
+ end_of_keysym++;
+ if(*end_of_keysym) {
+ int keysym;
+ *end_of_keysym=0;
+ keysym=get_keysym(line);
+ if(keysym==0) {
+ term_printf("Warning: 1unknown keysym %s\n",line);
+ } else {
+ const char* rest=end_of_keysym+1;
+ int keycode=parse_int(rest);
+ /* if(keycode&0x80)
+ keycode=(keycode<<8)^0x80e0; */
+ if(keysym<MAX_NORMAL_KEYCODE) {
+ //term_printf("Setting keysym %s (%d) to %d\n",line,keysym,keycode);
+ k->keysym2keycode[keysym]=keycode;
+#ifndef KEYBOARD_IGNORE_CASE
+ line[0]=toupper(line[0]);
+ keysym=get_keysym(line);
+ if(keysym)
+ k->keysym2keycode[keysym]=keycode;
+#endif
+ } else {
+ if(k->extra_count>=MAX_EXTRA_COUNT) {
+ term_printf("Warning: Could not assign keysym %s (0x%x) because of memory constraints.\n",line,keysym);
+ } else {
+ //term_printf("Setting %d: %d,%d\n",k->extra_count,keysym,keycode);
+ k->keysym2keycode_extra[k->extra_count].keysym=keysym;
+ k->keysym2keycode_extra[k->extra_count].keycode=keycode;
+ k->extra_count++;
+ }
+ }
+ }
+ }
+ }
+ }
+ fclose(f);
+ return k;
+}
+
+static void* init_keyboard_layout(const char* language)
+{
+ return parse_keyboard_layout(language,0);
+}
+
+static WORD keysym2scancode(void* kbd_layout, int keysym)
+{
+ kbd_layout_t* k=kbd_layout;
+ if(keysym<MAX_NORMAL_KEYCODE) {
+ if(k->keysym2keycode[keysym]==0)
+ term_printf("Warning: no scancode found for keysym %d\n",keysym);
+ return k->keysym2keycode[keysym];
+ } else {
+ int i;
+#ifdef XK_ISO_Left_Tab
+ if(keysym==XK_ISO_Left_Tab)
+ keysym=XK_Tab;
+#endif
+ for(i=0;i<k->extra_count;i++)
+ if(k->keysym2keycode_extra[i].keysym==keysym)
+ return k->keysym2keycode_extra[i].keycode;
+ }
+ return 0;
+}
+
--- /dev/null
+# generated from XKB map ar
+include common
+map 0x401
+exclam 0x02 shift
+at 0x03 shift
+numbersign 0x04 shift
+dollar 0x05 shift
+percent 0x06 shift
+asciicircum 0x07 shift
+ampersand 0x08 shift
+asterisk 0x09 shift
+parenleft 0x0a shift
+parenright 0x0b shift
+minus 0x0c
+underscore 0x0c shift
+equal 0x0d
+plus 0x0d shift
+Arabic_dad 0x10 altgr
+Arabic_fatha 0x10 shift altgr
+Arabic_sad 0x11 altgr
+Arabic_fathatan 0x11 shift altgr
+Arabic_theh 0x12 altgr
+Arabic_damma 0x12 shift altgr
+Arabic_qaf 0x13 altgr
+Arabic_dammatan 0x13 shift altgr
+Arabic_feh 0x14 altgr
+UFEF9 0x14 shift altgr
+Arabic_ghain 0x15 altgr
+Arabic_hamzaunderalef 0x15 shift altgr
+Arabic_ain 0x16 altgr
+grave 0x16 shift altgr
+Arabic_ha 0x17 altgr
+division 0x17 shift altgr
+Arabic_khah 0x18 altgr
+multiply 0x18 shift altgr
+Arabic_hah 0x19 altgr
+Arabic_semicolon 0x19 shift altgr
+bracketleft 0x1a
+braceleft 0x1a shift
+Arabic_jeem 0x1a altgr
+bracketright 0x1b
+braceright 0x1b shift
+Arabic_dal 0x1b altgr
+Arabic_sheen 0x1e altgr
+backslash 0x1e shift altgr
+Arabic_seen 0x1f altgr
+Arabic_yeh 0x20 altgr
+bracketleft 0x20 shift altgr
+Arabic_beh 0x21 altgr
+bracketright 0x21 shift altgr
+Arabic_lam 0x22 altgr
+UFEF7 0x22 shift altgr
+Arabic_alef 0x23 altgr
+Arabic_hamzaonalef 0x23 shift altgr
+Arabic_teh 0x24 altgr
+Arabic_tatweel 0x24 shift altgr
+Arabic_noon 0x25 altgr
+Arabic_comma 0x25 shift altgr
+Arabic_meem 0x26 altgr
+slash 0x26 shift altgr
+semicolon 0x27
+colon 0x27 shift
+Arabic_kaf 0x27 altgr
+apostrophe 0x28
+quotedbl 0x28 shift
+Arabic_tah 0x28 altgr
+grave 0x29
+asciitilde 0x29 shift
+Arabic_thal 0x29 altgr
+Arabic_shadda 0x29 shift altgr
+backslash 0x2b
+bar 0x2b shift
+less 0x2b altgr
+greater 0x2b shift altgr
+Arabic_hamzaonyeh 0x2c altgr
+asciitilde 0x2c shift altgr
+Arabic_hamza 0x2d altgr
+Arabic_sukun 0x2d shift altgr
+Arabic_hamzaonwaw 0x2e altgr
+Arabic_kasra 0x2e shift altgr
+Arabic_ra 0x2f altgr
+Arabic_kasratan 0x2f shift altgr
+UFEFB 0x30 altgr
+UFEF5 0x30 shift altgr
+Arabic_alefmaksura 0x31 altgr
+Arabic_maddaonalef 0x31 shift altgr
+Arabic_tehmarbuta 0x32 altgr
+apostrophe 0x32 shift altgr
+comma 0x33
+less 0x33 shift
+Arabic_waw 0x33 altgr
+period 0x34
+greater 0x34 shift
+Arabic_zain 0x34 altgr
+slash 0x35
+question 0x35 shift
+Arabic_zah 0x35 altgr
+Arabic_question_mark 0x35 shift altgr
--- /dev/null
+include modifiers
+
+#
+# Top row
+#
+1 0x2
+2 0x3
+3 0x4
+4 0x5
+5 0x6
+6 0x7
+7 0x8
+8 0x9
+9 0xa
+0 0xb
+BackSpace 0xe
+
+#
+# QWERTY first row
+#
+Tab 0xf localstate
+ISO_Left_Tab 0xf shift
+q 0x10 addupper
+w 0x11 addupper
+e 0x12 addupper
+r 0x13 addupper
+t 0x14 addupper
+y 0x15 addupper
+u 0x16 addupper
+i 0x17 addupper
+o 0x18 addupper
+p 0x19 addupper
+
+#
+# QWERTY second row
+#
+a 0x1e addupper
+s 0x1f addupper
+d 0x20 addupper
+f 0x21 addupper
+g 0x22 addupper
+h 0x23 addupper
+j 0x24 addupper
+k 0x25 addupper
+l 0x26 addupper
+Return 0x1c localstate
+
+#
+# QWERTY third row
+#
+z 0x2c addupper
+x 0x2d addupper
+c 0x2e addupper
+v 0x2f addupper
+b 0x30 addupper
+n 0x31 addupper
+m 0x32 addupper
+
+space 0x39 localstate
+
+less 0x56
+greater 0x56 shift
+bar 0x56 altgr
+brokenbar 0x56 shift altgr
+
+#
+# Esc and Function keys
+#
+Escape 0x1 localstate
+F1 0x3b localstate
+F2 0x3c localstate
+F3 0x3d localstate
+F4 0x3e localstate
+F5 0x3f localstate
+F6 0x40 localstate
+F7 0x41 localstate
+F8 0x42 localstate
+F9 0x43 localstate
+F10 0x44 localstate
+F11 0x57 localstate
+F12 0x58 localstate
+
+# Printscreen, Scrollock and Pause
+# Printscreen really requires four scancodes (0xe0, 0x2a, 0xe0, 0x37),
+# but (0xe0, 0x37) seems to work.
+Print 0xb7 localstate
+Sys_Req 0xb7 localstate
+Execute 0xb7 localstate
+Scroll_Lock 0x46
+
+#
+# Insert - PgDown
+#
+Insert 0xd2 localstate
+Delete 0xd3 localstate
+Home 0xc7 localstate
+End 0xcf localstate
+Page_Up 0xc9 localstate
+Page_Down 0xd1 localstate
+
+#
+# Arrow keys
+#
+Left 0xcb localstate
+Up 0xc8 localstate
+Down 0xd0 localstate
+Right 0xcd localstate
+
+#
+# Numpad
+#
+Num_Lock 0x45
+KP_Divide 0xb5
+KP_Multiply 0x37
+KP_Subtract 0x4a
+KP_Add 0x4e
+KP_Enter 0x9c
+
+KP_Decimal 0x53 numlock
+KP_Separator 0x53 numlock
+KP_Delete 0x53
+
+KP_0 0x52 numlock
+KP_Insert 0x52
+
+KP_1 0x4f numlock
+KP_End 0x4f
+
+KP_2 0x50 numlock
+KP_Down 0x50
+
+KP_3 0x51 numlock
+KP_Next 0x51
+
+KP_4 0x4b numlock
+KP_Left 0x4b
+
+KP_5 0x4c numlock
+KP_Begin 0x4c
+
+KP_6 0x4d numlock
+KP_Right 0x4d
+
+KP_7 0x47 numlock
+KP_Home 0x47
+
+KP_8 0x48 numlock
+KP_Up 0x48
+
+KP_9 0x49 numlock
+KP_Prior 0x49
+
+Caps_Lock 0x3a
+#
+# Inhibited keys
+#
+Multi_key 0x0 inhibit
--- /dev/null
+#!/usr/bin/env python2
+# -*-Python-*-
+#
+#
+# Copyright (C) 2001 Peter Åstrand <peter@cendio.se>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+import sys
+
+def main():
+ f = open(sys.argv[1])
+ while 1:
+ line = f.readline()
+ if not line: break
+
+ if line.startswith("#") or line.startswith("include"):
+ print line,
+ continue
+
+ fields = line.split()
+
+ if line.startswith("map"):
+ print "map 0x%s" % fields[1]
+ continue
+
+ scancode = fields[0]
+ for pos in range(1, len(fields)):
+ keysym = fields[pos]
+
+ if pos == 1:
+ modifiers = ""
+ elif pos == 2:
+ modifiers = "shift"
+ elif pos == 3:
+ modifiers = "altgr"
+ elif pos == 4:
+ modifiers = "shift altgr"
+ else:
+ raise("Invalid line: %s" % line)
+
+ print "%s 0x%s %s" % (keysym, scancode, modifiers)
+
+
+
+if __name__ == "__main__":
+ if len(sys.argv) < 2:
+ print "Convert old-style keymaps to new style"
+ print "Usage: %s <old-style-keymap>" % sys.argv[0]
+ sys.exit(1)
+ else:
+ main()
--- /dev/null
+# generated from XKB map dk
+include common
+map 0x406
+exclam 0x02 shift
+exclamdown 0x02 altgr
+onesuperior 0x02 shift altgr
+quotedbl 0x03 shift
+at 0x03 altgr
+twosuperior 0x03 shift altgr
+numbersign 0x04 shift
+sterling 0x04 altgr
+threesuperior 0x04 shift altgr
+currency 0x05 shift
+dollar 0x05 altgr
+onequarter 0x05 shift altgr
+percent 0x06 shift
+onehalf 0x06 altgr
+cent 0x06 shift altgr
+ampersand 0x07 shift
+yen 0x07 altgr
+fiveeighths 0x07 shift altgr
+slash 0x08 shift
+braceleft 0x08 altgr
+division 0x08 shift altgr
+parenleft 0x09 shift
+bracketleft 0x09 altgr
+guillemotleft 0x09 shift altgr
+parenright 0x0a shift
+bracketright 0x0a altgr
+guillemotright 0x0a shift altgr
+equal 0x0b shift
+braceright 0x0b altgr
+degree 0x0b shift altgr
+plus 0x0c
+question 0x0c shift
+plusminus 0x0c altgr
+questiondown 0x0c shift altgr
+dead_acute 0x0d
+dead_grave 0x0d shift
+bar 0x0d altgr
+brokenbar 0x0d shift altgr
+Greek_OMEGA 0x10 shift altgr
+lstroke 0x11 altgr
+Lstroke 0x11 shift altgr
+EuroSign 0x12 altgr
+cent 0x12 shift altgr
+registered 0x13 altgr
+thorn 0x14 altgr
+THORN 0x14 shift altgr
+leftarrow 0x15 altgr
+yen 0x15 shift altgr
+downarrow 0x16 altgr
+uparrow 0x16 shift altgr
+rightarrow 0x17 altgr
+idotless 0x17 shift altgr
+oe 0x18 altgr
+OE 0x18 shift altgr
+thorn 0x19 altgr
+THORN 0x19 shift altgr
+aring 0x1a
+Aring 0x1a shift
+dead_diaeresis 0x1a altgr
+dead_abovering 0x1a shift altgr
+dead_diaeresis 0x1b
+dead_circumflex 0x1b shift
+dead_tilde 0x1b altgr
+dead_caron 0x1b shift altgr
+ordfeminine 0x1e altgr
+masculine 0x1e shift altgr
+ssharp 0x1f altgr
+section 0x1f shift altgr
+eth 0x20 altgr
+ETH 0x20 shift altgr
+dstroke 0x21 altgr
+ordfeminine 0x21 shift altgr
+eng 0x22 altgr
+ENG 0x22 shift altgr
+hstroke 0x23 altgr
+Hstroke 0x23 shift altgr
+kra 0x25 altgr
+lstroke 0x26 altgr
+Lstroke 0x26 shift altgr
+ae 0x27
+AE 0x27 shift
+oslash 0x28
+Ooblique 0x28 shift
+dead_caron 0x28 shift altgr
+onehalf 0x29
+section 0x29 shift
+threequarters 0x29 altgr
+paragraph 0x29 shift altgr
+apostrophe 0x2b
+asterisk 0x2b shift
+dead_doubleacute 0x2b altgr
+multiply 0x2b shift altgr
+guillemotleft 0x2c altgr
+guillemotright 0x2d altgr
+copyright 0x2e altgr
+leftdoublequotemark 0x2f altgr
+grave 0x2f shift altgr
+rightdoublequotemark 0x30 altgr
+mu 0x32 altgr
+masculine 0x32 shift altgr
+comma 0x33
+semicolon 0x33 shift
+dead_cedilla 0x33 altgr
+dead_ogonek 0x33 shift altgr
+period 0x34
+colon 0x34 shift
+periodcentered 0x34 altgr
+dead_abovedot 0x34 shift altgr
+minus 0x35
+underscore 0x35 shift
+hyphen 0x35 altgr
+macron 0x35 shift altgr
+nobreakspace 0x39 altgr
+less 0x56
+greater 0x56 shift
+backslash 0x56 altgr
+notsign 0x56 shift altgr
--- /dev/null
+# generated from XKB map de
+include common
+map 0x407
+exclam 0x02 shift
+onesuperior 0x02 altgr
+exclamdown 0x02 shift altgr
+quotedbl 0x03 shift
+twosuperior 0x03 altgr
+oneeighth 0x03 shift altgr
+section 0x04 shift
+threesuperior 0x04 altgr
+sterling 0x04 shift altgr
+dollar 0x05 shift
+onequarter 0x05 altgr
+currency 0x05 shift altgr
+percent 0x06 shift
+onehalf 0x06 altgr
+threeeighths 0x06 shift altgr
+ampersand 0x07 shift
+threequarters 0x07 altgr
+fiveeighths 0x07 shift altgr
+slash 0x08 shift
+braceleft 0x08 altgr
+seveneighths 0x08 shift altgr
+parenleft 0x09 shift
+bracketleft 0x09 altgr
+trademark 0x09 shift altgr
+parenright 0x0a shift
+bracketright 0x0a altgr
+plusminus 0x0a shift altgr
+equal 0x0b shift
+braceright 0x0b altgr
+ssharp 0x0c
+question 0x0c shift
+backslash 0x0c altgr
+questiondown 0x0c shift altgr
+acute 0x0d
+dead_acute 0x0d
+grave 0x0d shift
+dead_grave 0x0d shift
+dead_cedilla 0x0d altgr
+dead_ogonek 0x0d shift altgr
+at 0x10 altgr
+Greek_OMEGA 0x10 shift altgr
+EuroSign 0x12 altgr
+paragraph 0x13 altgr
+registered 0x13 shift altgr
+tslash 0x14 altgr
+Tslash 0x14 shift altgr
+z 0x15 addupper
+leftarrow 0x15 altgr
+yen 0x15 shift altgr
+downarrow 0x16 altgr
+uparrow 0x16 shift altgr
+rightarrow 0x17 altgr
+idotless 0x17 shift altgr
+oslash 0x18 altgr
+Ooblique 0x18 shift altgr
+thorn 0x19 altgr
+THORN 0x19 shift altgr
+udiaeresis 0x1a
+Udiaeresis 0x1a shift
+dead_diaeresis 0x1a altgr
+dead_abovering 0x1a shift altgr
+plus 0x1b
+asterisk 0x1b shift
+asciitilde 0x1b altgr
+dead_tilde 0x1b altgr
+dead_macron 0x1b shift altgr
+ae 0x1e altgr
+AE 0x1e shift altgr
+eth 0x20 altgr
+ETH 0x20 shift altgr
+dstroke 0x21 altgr
+ordfeminine 0x21 shift altgr
+eng 0x22 altgr
+ENG 0x22 shift altgr
+hstroke 0x23 altgr
+Hstroke 0x23 shift altgr
+kra 0x25 altgr
+odiaeresis 0x27
+Odiaeresis 0x27 shift
+dead_doubleacute 0x27 altgr
+adiaeresis 0x28
+Adiaeresis 0x28 shift
+dead_caron 0x28 shift altgr
+asciicircum 0x29
+dead_circumflex 0x29
+degree 0x29 shift
+notsign 0x29 altgr
+numbersign 0x2b
+apostrophe 0x2b shift
+dead_breve 0x2b shift altgr
+y 0x2c addupper
+guillemotleft 0x2c altgr
+guillemotright 0x2d altgr
+cent 0x2e altgr
+copyright 0x2e shift altgr
+leftdoublequotemark 0x2f altgr
+rightdoublequotemark 0x30 altgr
+mu 0x32 altgr
+masculine 0x32 shift altgr
+comma 0x33
+semicolon 0x33 shift
+horizconnector 0x33 altgr
+multiply 0x33 shift altgr
+period 0x34
+colon 0x34 shift
+periodcentered 0x34 altgr
+division 0x34 shift altgr
+minus 0x35
+underscore 0x35 shift
+dead_belowdot 0x35 altgr
+dead_abovedot 0x35 shift altgr
--- /dev/null
+# rdesktop Swiss-German (de-ch) keymap file
+# 2003-06-03 by noldi@tristar.ch
+#
+include common
+map 0x00000807
+#
+# Scan Code 1
+section 0x29
+degree 0x29 shift
+notsign 0x29 altgr inhibit
+#
+# Scan Code 2
+plus 0x2 shift
+brokenbar 0x02 altgr
+#
+# Scan Code 3
+quotedbl 0x03 shift
+at 0x03 altgr
+#
+# Scan Code 4
+asterisk 0x04 shift
+numbersign 0x04 altgr
+#
+# Scan Code 5
+ccedilla 0x05 shift
+onequarter 0x05 altgr inhibit
+#
+# Scan Code 6
+percent 0x06 shift
+onehalf 0x06 altgr inhibit
+#
+# Scan Code 7
+ampersand 0x07 shift
+notsign 0x07 altgr
+#
+# Scan Code 8
+slash 0x08 shift
+bar 0x08 altgr
+#
+# Scan Code 9
+parenleft 0x09 shift
+cent 0x09 altgr
+#
+# Scan Code 10
+parenright 0x0a shift
+#
+# Scan Code 11
+equal 0x0b shift
+braceright 0x0b altgr inhibit
+#
+# Scan Code 12
+apostrophe 0x0c
+question 0x0c shift
+dead_acute 0x0c altgr
+#
+# Scan Code 13
+dead_circumflex 0x0d
+dead_grave 0x0d shift
+dead_tilde 0x0d altgr
+#
+# Scan Code 19
+EuroSign 0x12 altgr
+#
+# Scan Code 22
+z 0x15 addupper
+#
+# Scan Code 27
+udiaeresis 0x1a
+egrave 0x1a shift
+bracketleft 0x1a altgr
+#
+# Scan Code 28
+dead_diaeresis 0x1b
+exclam 0x1b shift
+bracketright 0x1b altgr
+#
+# Scan Code 40
+odiaeresis 0x27
+eacute 0x27 shift
+#
+# Scan Code 41
+adiaeresis 0x28
+agrave 0x28 shift
+braceleft 0x28 altgr
+#
+# Scan Code 42 (only on international keyboards)
+dollar 0x2b
+sterling 0x2b shift
+braceright 0x2b altgr
+#
+# Scan Code 45 (only on international keyboards)
+backslash 0x56 altgr
+#
+# Scan Code 46
+y 0x2c addupper
+#
+# Scan Code 53
+comma 0x33
+semicolon 0x33 shift
+#
+# Scan Code 54
+period 0x34
+colon 0x34 shift
+#
+# Scan Code 55
+minus 0x35
+underscore 0x35 shift
+#
+# Suppress Windows unsupported AltGr keys
+#
+# Scan Code 17
+paragraph 0x10 altgr inhibit
+#
+# Scan Code 21
+tslash 0x14 altgr inhibit
+#
+# Scan Code 22
+leftarrow 0x15 altgr inhibit
+#
+# Scan Code 23
+downarrow 0x16 altgr inhibit
+#
+# Scan Code 24
+rightarrow 0x17 altgr inhibit
+#
+# Scan Code 25
+oslash 0x18 altgr inhibit
+#
+# Scan Code 26
+thorn 0x19 altgr inhibit
+#
+# Scan Code 31
+ae 0x1e altgr inhibit
+#
+# Scan Code 32
+ssharp 0x1f altgr inhibit
+#
+# Scan Code 33
+eth 0x20 altgr inhibit
+#
+# Scan Code 34
+dstroke 0x21 altgr inhibit
+#
+# Scan Code 35
+eng 0x22 altgr inhibit
+#
+# Scan Code 36
+hstroke 0x23 altgr inhibit
+#
+# Scan Code 38
+kra 0x25 altgr inhibit
+#
+# Scan Code 39
+lstroke 0x26 altgr inhibit
+#
+# Scan Code 46
+guillemotleft 0x2c altgr inhibit
+#
+# Scan Code 47
+guillemotright 0x2d altgr inhibit
+#
+# Scan Code 49
+leftdoublequotemark 0x2f altgr inhibit
+#
+# Scan Code 50
+rightdoublequotemark 0x30 altgr inhibit
+#
+# Scan Code 52
+mu 0x32 altgr inhibit
--- /dev/null
+# generated from XKB map gb
+include common
+map 0x809
+exclam 0x02 shift
+onesuperior 0x02 altgr
+exclamdown 0x02 shift altgr
+quotedbl 0x03 shift
+twosuperior 0x03 altgr
+oneeighth 0x03 shift altgr
+sterling 0x04 shift
+threesuperior 0x04 altgr
+dollar 0x05 shift
+EuroSign 0x05 altgr
+percent 0x06 shift
+onehalf 0x06 altgr
+threeeighths 0x06 shift altgr
+asciicircum 0x07 shift
+threequarters 0x07 altgr
+fiveeighths 0x07 shift altgr
+ampersand 0x08 shift
+braceleft 0x08 altgr
+seveneighths 0x08 shift altgr
+asterisk 0x09 shift
+bracketleft 0x09 altgr
+trademark 0x09 shift altgr
+parenleft 0x0a shift
+bracketright 0x0a altgr
+plusminus 0x0a shift altgr
+parenright 0x0b shift
+braceright 0x0b altgr
+degree 0x0b shift altgr
+minus 0x0c
+underscore 0x0c shift
+backslash 0x0c altgr
+questiondown 0x0c shift altgr
+equal 0x0d
+plus 0x0d shift
+dead_cedilla 0x0d altgr
+dead_ogonek 0x0d shift altgr
+at 0x10 altgr
+Greek_OMEGA 0x10 shift altgr
+lstroke 0x11 altgr
+Lstroke 0x11 shift altgr
+paragraph 0x13 altgr
+registered 0x13 shift altgr
+tslash 0x14 altgr
+Tslash 0x14 shift altgr
+leftarrow 0x15 altgr
+yen 0x15 shift altgr
+downarrow 0x16 altgr
+uparrow 0x16 shift altgr
+rightarrow 0x17 altgr
+idotless 0x17 shift altgr
+oslash 0x18 altgr
+Ooblique 0x18 shift altgr
+thorn 0x19 altgr
+THORN 0x19 shift altgr
+bracketleft 0x1a
+braceleft 0x1a shift
+dead_diaeresis 0x1a altgr
+dead_abovering 0x1a shift altgr
+bracketright 0x1b
+braceright 0x1b shift
+dead_tilde 0x1b altgr
+dead_macron 0x1b shift altgr
+ae 0x1e altgr
+AE 0x1e shift altgr
+ssharp 0x1f altgr
+section 0x1f shift altgr
+eth 0x20 altgr
+ETH 0x20 shift altgr
+dstroke 0x21 altgr
+ordfeminine 0x21 shift altgr
+eng 0x22 altgr
+ENG 0x22 shift altgr
+hstroke 0x23 altgr
+Hstroke 0x23 shift altgr
+kra 0x25 altgr
+lstroke 0x26 altgr
+Lstroke 0x26 shift altgr
+semicolon 0x27
+colon 0x27 shift
+dead_acute 0x27 altgr
+dead_doubleacute 0x27 shift altgr
+apostrophe 0x28
+at 0x28 shift
+dead_circumflex 0x28 altgr
+dead_caron 0x28 shift altgr
+grave 0x29
+notsign 0x29 shift
+bar 0x29 altgr
+numbersign 0x2b
+asciitilde 0x2b shift
+dead_grave 0x2b altgr
+dead_breve 0x2b shift altgr
+guillemotleft 0x2c altgr
+less 0x2c shift altgr
+guillemotright 0x2d altgr
+greater 0x2d shift altgr
+cent 0x2e altgr
+copyright 0x2e shift altgr
+leftdoublequotemark 0x2f altgr
+rightdoublequotemark 0x30 altgr
+mu 0x32 altgr
+masculine 0x32 shift altgr
+comma 0x33
+less 0x33 shift
+horizconnector 0x33 altgr
+multiply 0x33 shift altgr
+period 0x34
+greater 0x34 shift
+periodcentered 0x34 altgr
+division 0x34 shift altgr
+slash 0x35
+question 0x35 shift
+dead_belowdot 0x35 altgr
+dead_abovedot 0x35 shift altgr
+backslash 0x56
+bar 0x56 shift
--- /dev/null
+# generated from XKB map us
+include common
+map 0x409
+exclam 0x02 shift
+at 0x03 shift
+numbersign 0x04 shift
+dollar 0x05 shift
+percent 0x06 shift
+asciicircum 0x07 shift
+ampersand 0x08 shift
+asterisk 0x09 shift
+parenleft 0x0a shift
+parenright 0x0b shift
+minus 0x0c
+underscore 0x0c shift
+equal 0x0d
+plus 0x0d shift
+bracketleft 0x1a
+braceleft 0x1a shift
+bracketright 0x1b
+braceright 0x1b shift
+semicolon 0x27
+colon 0x27 shift
+apostrophe 0x28
+quotedbl 0x28 shift
+grave 0x29
+asciitilde 0x29 shift
+backslash 0x2b
+bar 0x2b shift
+comma 0x33
+less 0x33 shift
+period 0x34
+greater 0x34 shift
+slash 0x35
+question 0x35 shift
--- /dev/null
+# generated from XKB map es
+include common
+map 0x40a
+exclam 0x02 shift
+bar 0x02 altgr
+quotedbl 0x03 shift
+at 0x03 altgr
+oneeighth 0x03 shift altgr
+periodcentered 0x04 shift
+numbersign 0x04 altgr
+sterling 0x04 shift altgr
+dollar 0x05 shift
+asciitilde 0x05 altgr
+percent 0x06 shift
+onehalf 0x06 altgr
+threeeighths 0x06 shift altgr
+ampersand 0x07 shift
+notsign 0x07 altgr
+fiveeighths 0x07 shift altgr
+slash 0x08 shift
+seveneighths 0x08 shift altgr
+parenleft 0x09 shift
+trademark 0x09 shift altgr
+parenright 0x0a shift
+plusminus 0x0a shift altgr
+equal 0x0b shift
+degree 0x0b shift altgr
+apostrophe 0x0c
+question 0x0c shift
+exclamdown 0x0d
+questiondown 0x0d shift
+Greek_OMEGA 0x10 shift altgr
+lstroke 0x11 altgr
+Lstroke 0x11 shift altgr
+EuroSign 0x12 altgr
+paragraph 0x13 altgr
+registered 0x13 shift altgr
+tslash 0x14 altgr
+Tslash 0x14 shift altgr
+leftarrow 0x15 altgr
+yen 0x15 shift altgr
+downarrow 0x16 altgr
+uparrow 0x16 shift altgr
+rightarrow 0x17 altgr
+idotless 0x17 shift altgr
+oslash 0x18 altgr
+Ooblique 0x18 shift altgr
+thorn 0x19 altgr
+THORN 0x19 shift altgr
+dead_grave 0x1a
+dead_circumflex 0x1a shift
+bracketleft 0x1a altgr
+dead_abovering 0x1a shift altgr
+plus 0x1b
+asterisk 0x1b shift
+bracketright 0x1b altgr
+dead_macron 0x1b shift altgr
+ae 0x1e altgr
+AE 0x1e shift altgr
+ssharp 0x1f altgr
+section 0x1f shift altgr
+eth 0x20 altgr
+ETH 0x20 shift altgr
+dstroke 0x21 altgr
+eng 0x22 altgr
+ENG 0x22 shift altgr
+hstroke 0x23 altgr
+Hstroke 0x23 shift altgr
+kra 0x25 altgr
+lstroke 0x26 altgr
+Lstroke 0x26 shift altgr
+ntilde 0x27
+Ntilde 0x27 shift
+dead_doubleacute 0x27 shift altgr
+dead_acute 0x28
+dead_diaeresis 0x28 shift
+braceleft 0x28 altgr
+masculine 0x29
+ordfeminine 0x29 shift
+backslash 0x29 altgr
+ccedilla 0x2b
+Ccedilla 0x2b shift
+braceright 0x2b altgr
+dead_breve 0x2b shift altgr
+guillemotleft 0x2c altgr
+less 0x56
+greater 0x56 shift
+guillemotright 0x2d altgr
+cent 0x2e altgr
+copyright 0x2e shift altgr
+leftdoublequotemark 0x2f altgr
+grave 0x2f shift altgr
+rightdoublequotemark 0x30 altgr
+mu 0x32 altgr
+comma 0x33
+semicolon 0x33 shift
+horizconnector 0x33 altgr
+multiply 0x33 shift altgr
+period 0x34
+colon 0x34 shift
+division 0x34 shift altgr
+minus 0x35
+underscore 0x35 shift
+dead_belowdot 0x35 altgr
+dead_abovedot 0x35 shift altgr
--- /dev/null
+map 0x00000425
+include common
+
+#
+# Top row
+#
+dead_caron 0x29
+dead_tilde 0x29 shift
+
+# 1
+exclam 0x2 shift
+
+# 2
+quotedbl 0x3 shift
+at 0x3 altgr
+
+# 3
+numbersign 0x4 shift
+sterling 0x4 altgr
+# 4
+currency 0x5 shift
+dollar 0x5 altgr
+# 5
+percent 0x6 shift
+# 6
+ampersand 0x7 shift
+# 7
+slash 0x8 shift
+braceleft 0x8 altgr
+# 8
+parenleft 0x9 shift
+bracketleft 0x9 altgr
+# 9
+parenright 0xa shift
+bracketright 0xa altgr
+# 0
+equal 0xb shift
+braceright 0xb altgr
+
+plus 0xc
+question 0xc shift
+backslash 0xc altgr
+
+acute 0xd
+dead_acute 0xd
+grave 0xd shift
+dead_grave 0xd shift
+
+#
+# QWERTY first row
+#
+EuroSign 0x12 altgr
+udiaeresis 0x1a
+Udiaeresis 0x1a shift
+otilde 0x1b
+Otilde 0x1b shift
+section 0x1b altgr
+
+#
+# QWERTY second row
+#
+scaron 0x1f altgr
+Scaron 0x1f altgr shift
+odiaeresis 0x27
+Odiaeresis 0x27 shift
+adiaeresis 0x28
+Adiaeresis 0x28 shift
+asciicircum 0x28 altgr
+apostrophe 0x2b
+asterisk 0x2b shift
+onehalf 0x2b altgr
+#
+# QWERTY third row
+#
+less 0x56
+greater 0x56 shift
+bar 0x56 altgr
+zcaron 0x2c altgr
+Zcaron 0x2c altgr shift
+comma 0x33
+semicolon 0x33 shift
+period 0x34
+colon 0x34 shift
+minus 0x35
+underscore 0x35 shift
+
--- /dev/null
+# generated from XKB map se_FI
+include common
+map 0x40b
+exclam 0x02 shift
+exclamdown 0x02 altgr
+onesuperior 0x02 shift altgr
+quotedbl 0x03 shift
+at 0x03 altgr
+twosuperior 0x03 shift altgr
+numbersign 0x04 shift
+sterling 0x04 altgr
+threesuperior 0x04 shift altgr
+currency 0x05 shift
+dollar 0x05 altgr
+onequarter 0x05 shift altgr
+percent 0x06 shift
+onehalf 0x06 altgr
+cent 0x06 shift altgr
+ampersand 0x07 shift
+yen 0x07 altgr
+fiveeighths 0x07 shift altgr
+slash 0x08 shift
+braceleft 0x08 altgr
+division 0x08 shift altgr
+parenleft 0x09 shift
+bracketleft 0x09 altgr
+guillemotleft 0x09 shift altgr
+parenright 0x0a shift
+bracketright 0x0a altgr
+guillemotright 0x0a shift altgr
+equal 0x0b shift
+braceright 0x0b altgr
+degree 0x0b shift altgr
+plus 0x0c
+question 0x0c shift
+backslash 0x0c altgr
+questiondown 0x0c shift altgr
+dead_acute 0x0d
+dead_grave 0x0d shift
+plusminus 0x0d altgr
+notsign 0x0d shift altgr
+at 0x10 altgr
+Greek_OMEGA 0x10 shift altgr
+lstroke 0x11 altgr
+Lstroke 0x11 shift altgr
+EuroSign 0x12 altgr
+cent 0x12 shift altgr
+registered 0x13 altgr
+thorn 0x14 altgr
+THORN 0x14 shift altgr
+leftarrow 0x15 altgr
+yen 0x15 shift altgr
+downarrow 0x16 altgr
+uparrow 0x16 shift altgr
+rightarrow 0x17 altgr
+idotless 0x17 shift altgr
+oe 0x18 altgr
+OE 0x18 shift altgr
+thorn 0x19 altgr
+THORN 0x19 shift altgr
+aring 0x1a
+Aring 0x1a shift
+dead_diaeresis 0x1a altgr
+dead_abovering 0x1a shift altgr
+dead_diaeresis 0x1b
+dead_circumflex 0x1b shift
+dead_tilde 0x1b altgr
+dead_caron 0x1b shift altgr
+ordfeminine 0x1e altgr
+masculine 0x1e shift altgr
+ssharp 0x1f altgr
+section 0x1f shift altgr
+eth 0x20 altgr
+ETH 0x20 shift altgr
+dstroke 0x21 altgr
+ordfeminine 0x21 shift altgr
+eng 0x22 altgr
+ENG 0x22 shift altgr
+hstroke 0x23 altgr
+Hstroke 0x23 shift altgr
+kra 0x25 altgr
+ampersand 0x25 shift altgr
+lstroke 0x26 altgr
+Lstroke 0x26 shift altgr
+odiaeresis 0x27
+Odiaeresis 0x27 shift
+oslash 0x27 altgr
+Ooblique 0x27 shift altgr
+adiaeresis 0x28
+Adiaeresis 0x28 shift
+ae 0x28 altgr
+AE 0x28 shift altgr
+section 0x29
+onehalf 0x29 shift
+paragraph 0x29 altgr
+threequarters 0x29 shift altgr
+apostrophe 0x2b
+asterisk 0x2b shift
+acute 0x2b altgr
+multiply 0x2b shift altgr
+guillemotleft 0x2c altgr
+less 0x2c shift altgr
+guillemotright 0x2d altgr
+greater 0x2d shift altgr
+copyright 0x2e altgr
+leftdoublequotemark 0x2f altgr
+grave 0x2f shift altgr
+rightdoublequotemark 0x30 altgr
+apostrophe 0x30 shift altgr
+mu 0x32 altgr
+masculine 0x32 shift altgr
+comma 0x33
+semicolon 0x33 shift
+dead_cedilla 0x33 altgr
+dead_ogonek 0x33 shift altgr
+period 0x34
+colon 0x34 shift
+periodcentered 0x34 altgr
+dead_abovedot 0x34 shift altgr
+minus 0x35
+underscore 0x35 shift
+hyphen 0x35 altgr
+macron 0x35 shift altgr
+nobreakspace 0x39 altgr
--- /dev/null
+map 0x438
+include common
+
+#
+# Top row
+#
+onehalf 0x29
+section 0x29 shift
+
+# 1
+exclam 0x2 shift
+
+# 2
+quotedbl 0x3 shift
+at 0x3 altgr
+
+# 3
+numbersign 0x4 shift
+sterling 0x4 altgr
+# 4
+currency 0x5 shift
+dollar 0x5 altgr
+# 5
+percent 0x6 shift
+# 6
+ampersand 0x7 shift
+# 7
+slash 0x8 shift
+braceleft 0x8 altgr
+# 8
+parenleft 0x9 shift
+bracketleft 0x9 altgr
+# 9
+parenright 0xa shift
+bracketright 0xa altgr
+# 0
+equal 0xb shift
+braceright 0xb altgr
+
+plus 0xc
+question 0xc shift
+plusminus 0xc altgr
+
+bar 0xd altgr
+dead_acute 0xd
+
+#
+# QWERTY first row
+#
+EuroSign 0x12 altgr
+aring 0x1a
+Aring 0x1a shift
+eth 0x1b addupper
+asciitilde 0x1b altgr
+
+#
+# QWERTY second row
+#
+ae 0x27 addupper
+oslash 0x28
+Ooblique 0x28 shift
+apostrophe 0x2b
+asterisk 0x2b shift
+
+#
+# QWERTY third row
+#
+less 0x56
+greater 0x56 shift
+backslash 0x56 altgr
+comma 0x33
+semicolon 0x33 shift
+period 0x34
+colon 0x34 shift
+minus 0x35
+underscore 0x35 shift
+
--- /dev/null
+include common
+map 0x40c
+#
+# Top row
+#
+twosuperior 0x29
+notsign 0x29 altgr
+
+ampersand 0x02
+1 0x02 shift
+onesuperior 0x02 altgr
+exclamdown 0x02 shift altgr
+
+eacute 0x03
+2 0x03 shift
+asciitilde 0x03 altgr
+oneeighth 0x03 shift altgr
+
+quotedbl 0x04
+3 0x04 shift
+numbersign 0x04 altgr
+
+apostrophe 0x05
+4 0x05 shift
+braceleft 0x05 altgr
+
+parenleft 0x06
+5 0x06 shift
+bracketleft 0x06 altgr
+threeeighths 0x06 shift altgr
+
+minus 0x07
+6 0x07 shift
+bar 0x07 altgr
+fiveeighths 0x07 shift altgr
+
+egrave 0x08
+7 0x08 shift
+grave 0x08 altgr
+seveneighths 0x08 shift altgr
+
+underscore 0x09
+8 0x09 shift
+backslash 0x09 altgr
+trademark 0x09 shift altgr
+
+ccedilla 0x0a
+9 0x0a shift
+asciicircum 0x0a altgr
+plusminus 0x0a shift altgr
+
+agrave 0x0b
+0 0x0b shift
+at 0x0b altgr
+
+parenright 0x0c
+degree 0x0c shift
+bracketright 0x0c altgr
+questiondown 0x0c shift altgr
+
+equal 0x0d
+plus 0x0d shift
+braceright 0x0d altgr
+dead_ogonek 0x0d shift altgr
+
+#
+# AZERTY first row
+#
+
+a 0x10 addupper
+ae 0x10 altgr
+AE 0x10 shift altgr
+
+z 0x11 addupper
+guillemotleft 0x11 altgr
+
+EuroSign 0x12 altgr
+
+paragraph 0x13 altgr
+registered 0x13 shift altgr
+
+tslash 0x14 altgr
+Tslash 0x14 shift altgr
+
+leftarrow 0x15 altgr
+yen 0x15 shift altgr
+
+downarrow 0x16 altgr
+uparrow 0x16 shift altgr
+
+rightarrow 0x17 altgr
+idotless 0x17 shift altgr
+
+oslash 0x18 altgr
+Ooblique 0x18 shift altgr
+
+thorn 0x19 altgr
+THORN 0x19 shift altgr
+
+dead_circumflex 0x1a
+dead_diaeresis 0x1a shift
+dead_abovering 0x1a shift altgr
+
+dollar 0x1b
+sterling 0x1b shift
+currency 0x1b altgr
+dead_macron 0x1b shift altgr
+
+#
+# AZERTY second row
+#
+q 0x1e addupper
+Greek_OMEGA 0x1e shift altgr
+
+ssharp 0x1f altgr
+
+eth 0x20 altgr
+ETH 0x20 shift altgr
+
+dstroke 0x21 altgr
+ordfeminine 0x21 shift altgr
+
+eng 0x22 altgr
+ENG 0x22 shift altgr
+
+hstroke 0x23 altgr
+Hstroke 0x23 shift altgr
+
+kra 0x25 altgr
+
+lstroke 0x26 altgr
+Lstroke 0x26 shift altgr
+
+m 0x27 addupper
+masculine 0x27 shift altgr
+
+ugrave 0x28
+percent 0x28 shift
+dead_caron 0x28 shift altgr
+
+asterisk 0x2b
+mu 0x2b shift
+dead_grave 0x2b altgr
+dead_breve 0x2b shift altgr
+
+#
+# AZERTY third row
+#
+less 0x56
+greater 0x56 shift
+
+w 0x2c addupper
+
+guillemotright 0x2d altgr
+
+cent 0x2e altgr
+copyright 0x2e shift altgr
+
+leftdoublequotemark 0x2f altgr
+
+rightdoublequotemark 0x30 altgr
+
+comma 0x32
+question 0x32 shift
+dead_acute 0x32 altgr
+dead_doubleacute 0x32 shift altgr
+
+semicolon 0x33
+period 0x33 shift
+horizconnector 0x33 altgr
+multiply 0x33 shift altgr
+
+colon 0x34
+slash 0x34 shift
+periodcentered 0x34 altgr
+division 0x34 shift altgr
+
+exclam 0x35
+section 0x35 shift
+dead_belowdot 0x35 altgr
+dead_abovedot 0x35 shift altgr
--- /dev/null
+# generated from XKB map be
+include common
+map 0x80c
+ampersand 0x02
+1 0x02 shift
+bar 0x02 altgr
+exclamdown 0x02 shift altgr
+eacute 0x03
+2 0x03 shift
+at 0x03 altgr
+oneeighth 0x03 shift altgr
+quotedbl 0x04
+3 0x04 shift
+numbersign 0x04 altgr
+sterling 0x04 shift altgr
+apostrophe 0x05
+4 0x05 shift
+onequarter 0x05 altgr
+dollar 0x05 shift altgr
+parenleft 0x06
+5 0x06 shift
+onehalf 0x06 altgr
+threeeighths 0x06 shift altgr
+section 0x07
+6 0x07 shift
+asciicircum 0x07 altgr
+fiveeighths 0x07 shift altgr
+egrave 0x08
+7 0x08 shift
+braceleft 0x08 altgr
+seveneighths 0x08 shift altgr
+exclam 0x09
+8 0x09 shift
+bracketleft 0x09 altgr
+trademark 0x09 shift altgr
+ccedilla 0x0a
+9 0x0a shift
+braceleft 0x0a altgr
+plusminus 0x0a shift altgr
+agrave 0x0b
+0 0x0b shift
+braceright 0x0b altgr
+degree 0x0b shift altgr
+parenright 0x0c
+degree 0x0c shift
+backslash 0x0c altgr
+questiondown 0x0c shift altgr
+minus 0x0d
+underscore 0x0d shift
+dead_cedilla 0x0d altgr
+dead_ogonek 0x0d shift altgr
+a 0x10 addupper
+at 0x10 altgr
+Greek_OMEGA 0x10 shift altgr
+z 0x11 addupper
+lstroke 0x11 altgr
+Lstroke 0x11 shift altgr
+EuroSign 0x12 altgr
+cent 0x12 shift altgr
+paragraph 0x13 altgr
+registered 0x13 shift altgr
+tslash 0x14 altgr
+Tslash 0x14 shift altgr
+leftarrow 0x15 altgr
+yen 0x15 shift altgr
+downarrow 0x16 altgr
+uparrow 0x16 shift altgr
+rightarrow 0x17 altgr
+idotless 0x17 shift altgr
+oslash 0x18 altgr
+Ooblique 0x18 shift altgr
+thorn 0x19 altgr
+THORN 0x19 shift altgr
+dead_circumflex 0x1a
+dead_diaeresis 0x1a shift
+bracketleft 0x1a altgr
+dead_abovering 0x1a shift altgr
+dollar 0x1b
+asterisk 0x1b shift
+bracketright 0x1b altgr
+dead_macron 0x1b shift altgr
+q 0x1e addupper
+ae 0x1e altgr
+AE 0x1e shift altgr
+ssharp 0x1f altgr
+section 0x1f shift altgr
+eth 0x20 altgr
+ETH 0x20 shift altgr
+dstroke 0x21 altgr
+ordfeminine 0x21 shift altgr
+eng 0x22 altgr
+ENG 0x22 shift altgr
+hstroke 0x23 altgr
+Hstroke 0x23 shift altgr
+kra 0x25 altgr
+ampersand 0x25 shift altgr
+lstroke 0x26 altgr
+Lstroke 0x26 shift altgr
+m 0x27 addupper
+dead_acute 0x27 altgr
+dead_doubleacute 0x27 shift altgr
+ugrave 0x28
+percent 0x28 shift
+dead_acute 0x28 altgr
+dead_caron 0x28 shift altgr
+twosuperior 0x29
+threesuperior 0x29 shift
+notsign 0x29 altgr
+mu 0x2b
+sterling 0x2b shift
+dead_grave 0x2b altgr
+dead_breve 0x2b shift altgr
+w 0x2c addupper
+guillemotleft 0x2c altgr
+less 0x2c shift altgr
+guillemotright 0x2d altgr
+greater 0x2d shift altgr
+cent 0x2e altgr
+copyright 0x2e shift altgr
+leftdoublequotemark 0x2f altgr
+grave 0x2f shift altgr
+rightdoublequotemark 0x30 altgr
+apostrophe 0x30 shift altgr
+comma 0x32
+question 0x32 shift
+dead_cedilla 0x32 altgr
+masculine 0x32 shift altgr
+semicolon 0x33
+period 0x33 shift
+horizconnector 0x33 altgr
+multiply 0x33 shift altgr
+colon 0x34
+slash 0x34 shift
+periodcentered 0x34 altgr
+division 0x34 shift altgr
+equal 0x35
+plus 0x35 shift
+dead_tilde 0x35 altgr
+dead_abovedot 0x35 shift altgr
+backslash 0x56 altgr
--- /dev/null
+# Canadian French
+# By Simon Germain
+include common
+map 0xc0c
+
+backslash 0x29 altgr
+plusminus 0x2 altgr
+at 0x3 altgr
+sterling 0x4 altgr
+cent 0x5 altgr
+currency 0x6 altgr
+notsign 0x7 altgr
+bar 0x29 shift
+twosuperior 0x9 altgr
+threesuperior 0xa altgr
+onequarter 0xb altgr
+onehalf 0xc altgr
+threequarters 0xd altgr
+section 0x18 altgr
+paragraph 0x19 altgr
+bracketleft 0x1a altgr
+bracketright 0x1b altgr
+asciitilde 0x27 altgr
+braceleft 0x28 altgr
+braceright 0x2b altgr
+less 0x2b
+greater 0x2b shift
+guillemotleft 0x56
+guillemotright 0x56 shift
+degree 0x56 altgr
+mu 0x32 altgr
+eacute 0x35
+dead_acute 0x35 altgr
+dead_grave 0x28
+dead_circumflex 0x1a
+dead_circumflex 0x1a shift
+dead_cedilla 0x1b
+dead_diaeresis 0x1b shift
+exclam 0x2 shift
+quotedbl 0x3 shift
+slash 0x4 shift
+dollar 0x5 shift
+percent 0x6 shift
+question 0x7 shift
+ampersand 0x8 shift
+asterisk 0x9 shift
+parenleft 0xa shift
+parenright 0xb shift
+underscore 0xc shift
+plus 0xd shift
--- /dev/null
+# generated from XKB map fr_CH
+include common
+map 0x100c
+exclam 0x02 shift
+onesuperior 0x02 altgr
+exclamdown 0x02 shift altgr
+quotedbl 0x03 shift
+twosuperior 0x03 altgr
+oneeighth 0x03 shift altgr
+section 0x04 shift
+threesuperior 0x04 altgr
+sterling 0x04 shift altgr
+dollar 0x05 shift
+onequarter 0x05 altgr
+currency 0x05 shift altgr
+percent 0x06 shift
+onehalf 0x06 altgr
+threeeighths 0x06 shift altgr
+ampersand 0x07 shift
+threequarters 0x07 altgr
+fiveeighths 0x07 shift altgr
+slash 0x08 shift
+braceleft 0x08 altgr
+seveneighths 0x08 shift altgr
+parenleft 0x09 shift
+bracketleft 0x09 altgr
+trademark 0x09 shift altgr
+parenright 0x0a shift
+bracketright 0x0a altgr
+plusminus 0x0a shift altgr
+equal 0x0b shift
+braceright 0x0b altgr
+ssharp 0x0c
+question 0x0c shift
+backslash 0x0c altgr
+questiondown 0x0c shift altgr
+acute 0x0d
+dead_acute 0x0d
+grave 0x0d shift
+dead_grave 0x0d shift
+dead_cedilla 0x0d altgr
+dead_ogonek 0x0d shift altgr
+at 0x10 altgr
+Greek_OMEGA 0x10 shift altgr
+EuroSign 0x12 altgr
+paragraph 0x13 altgr
+registered 0x13 shift altgr
+tslash 0x14 altgr
+Tslash 0x14 shift altgr
+z 0x15 addupper
+leftarrow 0x15 altgr
+yen 0x15 shift altgr
+downarrow 0x16 altgr
+uparrow 0x16 shift altgr
+rightarrow 0x17 altgr
+idotless 0x17 shift altgr
+oslash 0x18 altgr
+Ooblique 0x18 shift altgr
+thorn 0x19 altgr
+THORN 0x19 shift altgr
+udiaeresis 0x1a
+Udiaeresis 0x1a shift
+dead_diaeresis 0x1a altgr
+dead_abovering 0x1a shift altgr
+plus 0x1b
+asterisk 0x1b shift
+asciitilde 0x1b altgr
+dead_tilde 0x1b altgr
+dead_macron 0x1b shift altgr
+ae 0x1e altgr
+AE 0x1e shift altgr
+eth 0x20 altgr
+ETH 0x20 shift altgr
+dstroke 0x21 altgr
+ordfeminine 0x21 shift altgr
+eng 0x22 altgr
+ENG 0x22 shift altgr
+hstroke 0x23 altgr
+Hstroke 0x23 shift altgr
+kra 0x25 altgr
+odiaeresis 0x27
+Odiaeresis 0x27 shift
+dead_doubleacute 0x27 altgr
+adiaeresis 0x28
+Adiaeresis 0x28 shift
+dead_caron 0x28 shift altgr
+asciicircum 0x29
+dead_circumflex 0x29
+degree 0x29 shift
+notsign 0x29 altgr
+numbersign 0x2b
+apostrophe 0x2b shift
+dead_breve 0x2b shift altgr
+y 0x2c addupper
+guillemotleft 0x2c altgr
+guillemotright 0x2d altgr
+cent 0x2e altgr
+copyright 0x2e shift altgr
+leftdoublequotemark 0x2f altgr
+rightdoublequotemark 0x30 altgr
+mu 0x32 altgr
+masculine 0x32 shift altgr
+comma 0x33
+semicolon 0x33 shift
+horizconnector 0x33 altgr
+multiply 0x33 shift altgr
+period 0x34
+colon 0x34 shift
+periodcentered 0x34 altgr
+division 0x34 shift altgr
+minus 0x35
+underscore 0x35 shift
+dead_belowdot 0x35 altgr
+dead_abovedot 0x35 shift altgr
--- /dev/null
+# generated from XKB map hr
+include common
+map 0x41a
+exclam 0x02 shift
+asciitilde 0x02 altgr
+dead_tilde 0x02 shift altgr
+quotedbl 0x03 shift
+dead_caron 0x03 altgr
+caron 0x03 shift altgr
+numbersign 0x04 shift
+asciicircum 0x04 altgr
+dead_circumflex 0x04 shift altgr
+dollar 0x05 shift
+dead_breve 0x05 altgr
+breve 0x05 shift altgr
+percent 0x06 shift
+degree 0x06 altgr
+dead_abovering 0x06 shift altgr
+ampersand 0x07 shift
+dead_ogonek 0x07 altgr
+ogonek 0x07 shift altgr
+slash 0x08 shift
+grave 0x08 altgr
+dead_grave 0x08 shift altgr
+parenleft 0x09 shift
+dead_abovedot 0x09 altgr
+abovedot 0x09 shift altgr
+parenright 0x0a shift
+dead_acute 0x0a altgr
+apostrophe 0x0a shift altgr
+equal 0x0b shift
+dead_doubleacute 0x0b altgr
+doubleacute 0x0b shift altgr
+apostrophe 0x0c
+question 0x0c shift
+dead_diaeresis 0x0c altgr
+diaeresis 0x0c shift altgr
+plus 0x0d
+asterisk 0x0d shift
+dead_cedilla 0x0d altgr
+cedilla 0x0d shift altgr
+backslash 0x10 altgr
+Greek_OMEGA 0x10 shift altgr
+bar 0x11 altgr
+Lstroke 0x11 shift altgr
+EuroSign 0x12 altgr
+paragraph 0x13 altgr
+registered 0x13 shift altgr
+tslash 0x14 altgr
+Tslash 0x14 shift altgr
+z 0x15 addupper
+leftarrow 0x15 altgr
+yen 0x15 shift altgr
+downarrow 0x16 altgr
+uparrow 0x16 shift altgr
+rightarrow 0x17 altgr
+idotless 0x17 shift altgr
+oslash 0x18 altgr
+Ooblique 0x18 shift altgr
+thorn 0x19 altgr
+THORN 0x19 shift altgr
+scaron 0x1a
+Scaron 0x1a shift
+division 0x1a altgr
+dead_abovering 0x1a shift altgr
+dstroke 0x1b
+Dstroke 0x1b shift
+multiply 0x1b altgr
+dead_macron 0x1b shift altgr
+ae 0x1e altgr
+AE 0x1e shift altgr
+ssharp 0x1f altgr
+section 0x1f shift altgr
+eth 0x20 altgr
+ETH 0x20 shift altgr
+bracketleft 0x21 altgr
+ordfeminine 0x21 shift altgr
+bracketright 0x22 altgr
+ENG 0x22 shift altgr
+hstroke 0x23 altgr
+Hstroke 0x23 shift altgr
+lstroke 0x25 altgr
+ampersand 0x25 shift altgr
+Lstroke 0x26 altgr
+ccaron 0x27
+Ccaron 0x27 shift
+dead_acute 0x27 altgr
+dead_doubleacute 0x27 shift altgr
+cacute 0x28
+Cacute 0x28 shift
+ssharp 0x28 altgr
+dead_caron 0x28 shift altgr
+dead_cedilla 0x29
+dead_diaeresis 0x29 shift
+notsign 0x29 altgr
+zcaron 0x2b
+Zcaron 0x2b shift
+currency 0x2b altgr
+dead_breve 0x2b shift altgr
+y 0x2c addupper
+guillemotleft 0x2c altgr
+less 0x2c shift altgr
+guillemotright 0x2d altgr
+greater 0x2d shift altgr
+cent 0x2e altgr
+copyright 0x2e shift altgr
+at 0x2f altgr
+grave 0x2f shift altgr
+braceleft 0x30 altgr
+apostrophe 0x30 shift altgr
+braceright 0x31 altgr
+section 0x32 altgr
+masculine 0x32 shift altgr
+comma 0x33
+semicolon 0x33 shift
+horizconnector 0x33 altgr
+multiply 0x33 shift altgr
+period 0x34
+colon 0x34 shift
+periodcentered 0x34 altgr
+division 0x34 shift altgr
+minus 0x35
+underscore 0x35 shift
+dead_belowdot 0x35 altgr
+dead_abovedot 0x35 shift altgr
--- /dev/null
+# Hungarian keyboard layout (QWERTZ)
+# Created by: The NeverGone <never@delfin.klte.hu>
+
+include common
+map 0x40e
+
+
+# AltGr keys:
+notsign 0x29 altgr
+asciitilde 0x02 altgr
+caron 0x03 altgr
+asciicircum 0x04 altgr
+breve 0x05 altgr
+degree 0x06 altgr
+ogonek 0x07 altgr
+grave 0x08 altgr
+abovedot 0x09 altgr
+acute 0x0a altgr
+doubleacute 0x0b altgr
+diaeresis 0x0c altgr
+cedilla 0x0d altgr
+backslash 0x10 altgr
+bar 0x11 altgr
+EuroSign 0x12 altgr
+Iacute 0x17 altgr
+division 0x1a altgr
+multiply 0x1b altgr
+dstroke 0x1f altgr
+Dstroke 0x20 altgr
+bracketleft 0x21 altgr
+bracketright 0x22 altgr
+iacute 0x24 altgr
+lstroke 0x25 altgr
+Lstroke 0x26 altgr
+dollar 0x27 altgr
+ssharp 0x28 altgr
+currency 0x2b altgr
+less 0x56 altgr
+greater 0x2c altgr
+numbersign 0x2d altgr
+ampersand 0x2e altgr
+at 0x2f altgr
+braceleft 0x30 altgr
+braceright 0x31 altgr
+semicolon 0x33 altgr
+asterisk 0x35 altgr
+
+
+# Shift keys:
+section 0x29 shift
+apostrophe 0x02 shift
+quotedbl 0x03 shift
+plus 0x04 shift
+exclam 0x05 shift
+percent 0x06 shift
+slash 0x07 shift
+equal 0x08 shift
+parenleft 0x09 shift
+parenright 0x0a shift
+Odiaeresis 0x0b shift
+Udiaeresis 0x0c shift
+Oacute 0x0d shift
+Z 0x15 shift
+Odoubleacute 0x1a shift
+Uacute 0x1b shift
+Eacute 0x27 shift
+Aacute 0x28 shift
+Udoubleacute 0x2b shift
+Y 0x2c shift
+question 0x33 shift
+colon 0x34 shift
+underscore 0x35 shift
+F13 0x3b shift
+F14 0x3c shift
+F15 0x3d shift
+F16 0x3e shift
+F17 0x3f shift
+F18 0x40 shift
+F19 0x41 shift
+F20 0x42 shift
+F21 0x43 shift
+F22 0x44 shift
+F23 0x57 shift
+F24 0x58 shift
+
+
+# Ctrl keys:
+F25 0x3b ctrl
+F26 0x3c ctrl
+F27 0x3d ctrl
+F28 0x3e ctrl
+F29 0x3f ctrl
+F30 0x40 ctrl
+F31 0x41 ctrl
+F32 0x42 ctrl
+F33 0x43 ctrl
+F34 0x44 ctrl
+F35 0x57 ctrl
+#NoSymbol 0x58 ctrl
+
+
+0 0x29
+odiaeresis 0x0b
+udiaeresis 0x0c
+oacute 0x0d
+z 0x15
+odoubleacute 0x1a
+uacute 0x1b
+eacute 0x27
+aacute 0x28
+udoubleacute 0x2b
+y 0x2c
+comma 0x33
+period 0x34
+minus 0x35
--- /dev/null
+# 2004-03-16 Halldór Guðmundsson and Morten Lange
+# Keyboard definition file for the Icelandic keyboard
+# to be used in rdesktop 1.3.x ( See rdesktop.org)
+# generated from XKB map de, and changed manually
+# Location for example /usr/local/share/rdesktop/keymaps/is
+include common
+map 0x40f
+exclam 0x02 shift
+onesuperior 0x02 altgr
+exclamdown 0x02 shift altgr
+quotedbl 0x03 shift
+twosuperior 0x03 altgr
+oneeighth 0x03 shift altgr
+#section 0x04 shift
+numbersign 0x04 shift
+threesuperior 0x04 altgr
+sterling 0x04 shift altgr
+dollar 0x05 shift
+onequarter 0x05 altgr
+currency 0x05 shift altgr
+percent 0x06 shift
+onehalf 0x06 altgr
+threeeighths 0x06 shift altgr
+ampersand 0x07 shift
+threequarters 0x07 altgr
+fiveeighths 0x07 shift altgr
+slash 0x08 shift
+braceleft 0x08 altgr
+seveneighths 0x08 shift altgr
+parenleft 0x09 shift
+bracketleft 0x09 altgr
+trademark 0x09 shift altgr
+parenright 0x0a shift
+bracketright 0x0a altgr
+plusminus 0x0a shift altgr
+equal 0x0b shift
+braceright 0x0b altgr
+#ssharp 0x0c
+odiaeresis 0x0c
+#question 0x0c shift
+Odiaeresis 0x0c shift
+backslash 0x0c altgr
+questiondown 0x0c shift altgr
+#acute 0x0d
+minus 0x0d
+#dead_acute 0x0d
+#grave 0x0d shift
+#dead_grave 0x0d shift
+underscore 0x0d shift
+dead_cedilla 0x0d altgr
+dead_ogonek 0x0d shift altgr
+at 0x10 altgr
+Greek_OMEGA 0x10 shift altgr
+EuroSign 0x12 altgr
+paragraph 0x13 altgr
+registered 0x13 shift altgr
+tslash 0x14 altgr
+Tslash 0x14 shift altgr
+#z 0x15 addupper
+leftarrow 0x15 altgr
+yen 0x15 shift altgr
+downarrow 0x16 altgr
+uparrow 0x16 shift altgr
+rightarrow 0x17 altgr
+idotless 0x17 shift altgr
+oslash 0x18 altgr
+Ooblique 0x18 shift altgr
+#thorn 0x19 altgr
+#THORN 0x19 shift altgr
+#udiaeresis 0x1a
+#Udiaeresis 0x1a shift
+#dead_diaeresis 0x1a altgr
+#dead_abovering 0x1a shift altgr
+eth 0x1a
+ETH 0x1a shift
+apostrophe 0x1b
+question 0x1b shift
+#plus 0x1b
+#asterisk 0x1b shift
+asciitilde 0x1b altgr
+#grave 0x1b altgr
+#dead_tilde 0x1b altgr
+#dead_macron 0x1b shift altgr
+#ae 0x1e altgr
+#AE 0x1e shift altgr
+#eth 0x20 altgr
+#eth 0x20
+#ETH 0x20 shift altgr
+#ETH 0x20 shift
+dstroke 0x21 altgr
+ordfeminine 0x21 shift altgr
+eng 0x22 altgr
+ENG 0x22 shift altgr
+hstroke 0x23 altgr
+Hstroke 0x23 shift altgr
+kra 0x25 altgr
+#adiaeresis 0x27
+#Adiaeresis 0x27 shift
+ae 0x27
+AE 0x27 shift
+dead_doubleacute 0x27 altgr
+#adiaeresis 0x28
+#Adiaeresis 0x28 shift
+#dead_caron 0x28 shift altgr
+#asciicircum 0x29
+acute 0x28
+dead_acute 0x28
+#dead_circumflex 0x29
+#degree 0x29 shift
+#notsign 0x29 altgr
+plus 0x2b
+asterisk 0x2b shift
+grave 0x2b altgr
+#numbersign 0x2b
+#apostrophe 0x2b shift
+#dead_breve 0x2b shift altgr
+#y 0x2c addupper
+guillemotleft 0x2c altgr
+guillemotright 0x2d altgr
+cent 0x2e altgr
+copyright 0x2e shift altgr
+leftdoublequotemark 0x2f altgr
+rightdoublequotemark 0x30 altgr
+mu 0x32 altgr
+masculine 0x32 shift altgr
+comma 0x33
+semicolon 0x33 shift
+horizconnector 0x33 altgr
+multiply 0x33 shift altgr
+period 0x34
+colon 0x34 shift
+periodcentered 0x34 altgr
+division 0x34 shift altgr
+#minus 0x35
+#underscore 0x35 shift
+thorn 0x35
+THORN 0x35 shift
+dead_belowdot 0x35 altgr
+dead_abovedot 0x35 shift altgr
+
--- /dev/null
+# generated from XKB map it
+include common
+map 0x410
+exclam 0x02 shift
+onesuperior 0x02 altgr
+exclamdown 0x02 shift altgr
+quotedbl 0x03 shift
+twosuperior 0x03 altgr
+oneeighth 0x03 shift altgr
+sterling 0x04 shift
+threesuperior 0x04 altgr
+dollar 0x05 shift
+onequarter 0x05 altgr
+percent 0x06 shift
+onehalf 0x06 altgr
+threeeighths 0x06 shift altgr
+ampersand 0x07 shift
+threequarters 0x07 altgr
+fiveeighths 0x07 shift altgr
+slash 0x08 shift
+braceleft 0x08 altgr
+seveneighths 0x08 shift altgr
+parenleft 0x09 shift
+trademark 0x09 shift altgr
+parenright 0x0a shift
+plusminus 0x0a shift altgr
+equal 0x0b shift
+braceright 0x0b altgr
+degree 0x0b shift altgr
+apostrophe 0x0c
+question 0x0c shift
+grave 0x0c altgr
+questiondown 0x0c shift altgr
+igrave 0x0d
+asciicircum 0x0d shift
+asciitilde 0x0d altgr
+dead_ogonek 0x0d shift altgr
+at 0x10 altgr
+Greek_OMEGA 0x10 shift altgr
+lstroke 0x11 altgr
+Lstroke 0x11 shift altgr
+EuroSign 0x12 altgr
+cent 0x12 shift altgr
+paragraph 0x13 altgr
+registered 0x13 shift altgr
+tslash 0x14 altgr
+Tslash 0x14 shift altgr
+leftarrow 0x15 altgr
+yen 0x15 shift altgr
+downarrow 0x16 altgr
+uparrow 0x16 shift altgr
+rightarrow 0x17 altgr
+idotless 0x17 shift altgr
+oslash 0x18 altgr
+Ooblique 0x18 shift altgr
+thorn 0x19 altgr
+THORN 0x19 shift altgr
+egrave 0x1a
+eacute 0x1a shift
+bracketleft 0x1a altgr
+dead_abovering 0x1a shift altgr
+plus 0x1b
+asterisk 0x1b shift
+bracketright 0x1b altgr
+dead_macron 0x1b shift altgr
+ae 0x1e altgr
+AE 0x1e shift altgr
+ssharp 0x1f altgr
+section 0x1f shift altgr
+eth 0x20 altgr
+ETH 0x20 shift altgr
+dstroke 0x21 altgr
+ordfeminine 0x21 shift altgr
+eng 0x22 altgr
+ENG 0x22 shift altgr
+hstroke 0x23 altgr
+Hstroke 0x23 shift altgr
+kra 0x25 altgr
+lstroke 0x26 altgr
+Lstroke 0x26 shift altgr
+ograve 0x27
+ccedilla 0x27 shift
+at 0x27 altgr
+dead_doubleacute 0x27 shift altgr
+agrave 0x28
+degree 0x28 shift
+numbersign 0x28 altgr
+backslash 0x29
+bar 0x29 shift
+notsign 0x29 altgr
+ugrave 0x2b
+section 0x2b shift
+dead_grave 0x2b altgr
+dead_breve 0x2b shift altgr
+guillemotleft 0x2c altgr
+guillemotright 0x2d altgr
+cent 0x2e altgr
+copyright 0x2e shift altgr
+leftdoublequotemark 0x2f altgr
+grave 0x2f shift altgr
+rightdoublequotemark 0x30 altgr
+mu 0x32 altgr
+masculine 0x32 shift altgr
+comma 0x33
+semicolon 0x33 shift
+horizconnector 0x33 altgr
+multiply 0x33 shift altgr
+period 0x34
+colon 0x34 shift
+periodcentered 0x34 altgr
+division 0x34 shift altgr
+minus 0x35
+underscore 0x35 shift
+dead_belowdot 0x35 altgr
+dead_abovedot 0x35 shift altgr
--- /dev/null
+# generated from XKB map jp106
+include common
+map 0x411
+exclam 0x02 shift
+kana_NU 0x02 altgr
+quotedbl 0x03 shift
+kana_FU 0x03 altgr
+numbersign 0x04 shift
+kana_A 0x04 altgr
+kana_a 0x04 shift altgr
+dollar 0x05 shift
+kana_U 0x05 altgr
+kana_u 0x05 shift altgr
+percent 0x06 shift
+kana_E 0x06 altgr
+kana_e 0x06 shift altgr
+ampersand 0x07 shift
+kana_O 0x07 altgr
+kana_o 0x07 shift altgr
+apostrophe 0x08 shift
+kana_YA 0x08 altgr
+kana_ya 0x08 shift altgr
+parenleft 0x09 shift
+kana_YU 0x09 altgr
+kana_yu 0x09 shift altgr
+parenright 0x0a shift
+kana_YO 0x0a altgr
+kana_yo 0x0a shift altgr
+asciitilde 0x0b shift
+kana_WA 0x0b altgr
+kana_WO 0x0b shift altgr
+minus 0x0c
+equal 0x0c shift
+kana_HO 0x0c altgr
+asciicircum 0x0d
+asciitilde 0x0d shift
+kana_HE 0x0d altgr
+kana_TA 0x10 altgr
+kana_TE 0x11 altgr
+kana_I 0x12 altgr
+kana_i 0x12 shift altgr
+kana_SU 0x13 altgr
+kana_KA 0x14 altgr
+kana_N 0x15 altgr
+kana_NA 0x16 altgr
+kana_NI 0x17 altgr
+kana_RA 0x18 altgr
+kana_SE 0x19 altgr
+at 0x1a
+grave 0x1a shift
+voicedsound 0x1a altgr
+bracketleft 0x1b
+braceleft 0x1b shift
+semivoicedsound 0x1b altgr
+kana_openingbracket 0x1b shift altgr
+kana_CHI 0x1e altgr
+kana_TO 0x1f altgr
+kana_SHI 0x20 altgr
+kana_HA 0x21 altgr
+kana_KI 0x22 altgr
+kana_KU 0x23 altgr
+kana_MA 0x24 altgr
+kana_NO 0x25 altgr
+kana_RI 0x26 altgr
+semicolon 0x27
+plus 0x27 shift
+kana_RE 0x27 altgr
+colon 0x28
+asterisk 0x28 shift
+kana_KE 0x28 altgr
+Zenkaku_Hankaku 0x29
+bracketright 0x2b
+braceright 0x2b shift
+kana_MU 0x2b altgr
+kana_closingbracket 0x2b shift altgr
+kana_TSU 0x2c altgr
+kana_tsu 0x2c shift altgr
+kana_SA 0x2d altgr
+kana_SO 0x2e altgr
+kana_HI 0x2f altgr
+kana_KO 0x30 altgr
+kana_MI 0x31 altgr
+kana_MO 0x32 altgr
+comma 0x33
+less 0x33 shift
+kana_NE 0x33 altgr
+kana_comma 0x33 shift altgr
+period 0x34
+greater 0x34 shift
+kana_RU 0x34 altgr
+kana_fullstop 0x34 shift altgr
+slash 0x35
+question 0x35 shift
+kana_ME 0x35 altgr
+kana_conjunctive 0x35 shift altgr
+Eisu_toggle 0x3a shift
+Execute 0x54 shift
+Kanji 0x70
+backslash 0x73
+bar 0x7d shift
+underscore 0x73 shift
+Henkan_Mode 0x79
+Katakana 0x70
+Muhenkan 0x7b
--- /dev/null
+# generated from XKB map lt
+include common
+map 0x427
+exclam 0x02 shift
+aogonek 0x02 altgr
+Aogonek 0x02 shift altgr
+at 0x03 shift
+ccaron 0x03 altgr
+Ccaron 0x03 shift altgr
+numbersign 0x04 shift
+eogonek 0x04 altgr
+Eogonek 0x04 shift altgr
+dollar 0x05 shift
+eabovedot 0x05 altgr
+Eabovedot 0x05 shift altgr
+percent 0x06 shift
+iogonek 0x06 altgr
+Iogonek 0x06 shift altgr
+asciicircum 0x07 shift
+scaron 0x07 altgr
+Scaron 0x07 shift altgr
+ampersand 0x08 shift
+uogonek 0x08 altgr
+Uogonek 0x08 shift altgr
+asterisk 0x09 shift
+umacron 0x09 altgr
+Umacron 0x09 shift altgr
+parenleft 0x0a shift
+doublelowquotemark 0x0a altgr
+parenright 0x0b shift
+leftdoublequotemark 0x0b altgr
+minus 0x0c
+underscore 0x0c shift
+equal 0x0d
+plus 0x0d shift
+zcaron 0x0d altgr
+Zcaron 0x0d shift altgr
+bracketleft 0x1a
+braceleft 0x1a shift
+bracketright 0x1b
+braceright 0x1b shift
+semicolon 0x27
+colon 0x27 shift
+apostrophe 0x28
+quotedbl 0x28 shift
+grave 0x29
+asciitilde 0x29 shift
+backslash 0x2b
+bar 0x2b shift
+comma 0x33
+less 0x33 shift
+period 0x34
+greater 0x34 shift
+slash 0x35
+question 0x35 shift
+endash 0x56
+EuroSign 0x56 shift
--- /dev/null
+# generated from XKB map lv
+include common
+map 0x426
+exclam 0x02 shift
+onesuperior 0x02 altgr
+exclamdown 0x02 shift altgr
+at 0x03 shift
+twosuperior 0x03 altgr
+oneeighth 0x03 shift altgr
+numbersign 0x04 shift
+threesuperior 0x04 altgr
+sterling 0x04 shift altgr
+dollar 0x05 shift
+EuroSign 0x05 altgr
+cent 0x05 shift altgr
+percent 0x06 shift
+onehalf 0x06 altgr
+threeeighths 0x06 shift altgr
+asciicircum 0x07 shift
+threequarters 0x07 altgr
+fiveeighths 0x07 shift altgr
+ampersand 0x08 shift
+braceleft 0x08 altgr
+seveneighths 0x08 shift altgr
+asterisk 0x09 shift
+bracketleft 0x09 altgr
+trademark 0x09 shift altgr
+parenleft 0x0a shift
+bracketright 0x0a altgr
+plusminus 0x0a shift altgr
+parenright 0x0b shift
+braceright 0x0b altgr
+degree 0x0b shift altgr
+minus 0x0c
+underscore 0x0c shift
+backslash 0x0c altgr
+questiondown 0x0c shift altgr
+equal 0x0d
+plus 0x0d shift
+dead_cedilla 0x0d altgr
+dead_ogonek 0x0d shift altgr
+at 0x10 altgr
+Greek_OMEGA 0x10 shift altgr
+lstroke 0x11 altgr
+Lstroke 0x11 shift altgr
+emacron 0x12 altgr
+Emacron 0x12 shift altgr
+rcedilla 0x13 altgr
+Rcedilla 0x13 shift altgr
+tslash 0x14 altgr
+Tslash 0x14 shift altgr
+leftarrow 0x15 altgr
+yen 0x15 shift altgr
+umacron 0x16 altgr
+Umacron 0x16 shift altgr
+imacron 0x17 altgr
+Imacron 0x17 shift altgr
+omacron 0x18 altgr
+Omacron 0x18 shift altgr
+thorn 0x19 altgr
+THORN 0x19 shift altgr
+bracketleft 0x1a
+braceleft 0x1a shift
+dead_diaeresis 0x1a altgr
+dead_abovering 0x1a shift altgr
+bracketright 0x1b
+braceright 0x1b shift
+dead_tilde 0x1b altgr
+dead_macron 0x1b shift altgr
+ISO_Next_Group 0x1c shift
+amacron 0x1e altgr
+Amacron 0x1e shift altgr
+scaron 0x1f altgr
+Scaron 0x1f shift altgr
+eth 0x20 altgr
+ETH 0x20 shift altgr
+dstroke 0x21 altgr
+ordfeminine 0x21 shift altgr
+gcedilla 0x22 altgr
+Gcedilla 0x22 shift altgr
+hstroke 0x23 altgr
+Hstroke 0x23 shift altgr
+kcedilla 0x25 altgr
+Kcedilla 0x25 shift altgr
+lcedilla 0x26 altgr
+Lcedilla 0x26 shift altgr
+semicolon 0x27
+colon 0x27 shift
+dead_acute 0x27 altgr
+dead_doubleacute 0x27 shift altgr
+apostrophe 0x28
+quotedbl 0x28 shift
+leftdoublequotemark 0x28 altgr
+doublelowquotemark 0x28 shift altgr
+grave 0x29
+asciitilde 0x29 shift
+notsign 0x29 altgr
+backslash 0x2b
+bar 0x2b shift
+dead_grave 0x2b altgr
+dead_breve 0x2b shift altgr
+zcaron 0x2c altgr
+Zcaron 0x2c shift altgr
+guillemotright 0x2d altgr
+greater 0x2d shift altgr
+ccaron 0x2e altgr
+Ccaron 0x2e shift altgr
+leftdoublequotemark 0x2f altgr
+grave 0x2f shift altgr
+rightdoublequotemark 0x30 altgr
+apostrophe 0x30 shift altgr
+ncedilla 0x31 altgr
+Ncedilla 0x31 shift altgr
+mu 0x32 altgr
+masculine 0x32 shift altgr
+comma 0x33
+less 0x33 shift
+horizconnector 0x33 altgr
+multiply 0x33 shift altgr
+period 0x34
+greater 0x34 shift
+periodcentered 0x34 altgr
+division 0x34 shift altgr
+slash 0x35
+question 0x35 shift
+dead_belowdot 0x35 altgr
+dead_abovedot 0x35 shift altgr
+nobreakspace 0x39 altgr
--- /dev/null
+# generated from XKB map mk
+include common
+map 0x42f
+exclam 0x02 shift
+at 0x03 shift
+doublelowquotemark 0x03 shift altgr
+numbersign 0x04 shift
+leftdoublequotemark 0x04 shift altgr
+dollar 0x05 shift
+percent 0x06 shift
+asciicircum 0x07 shift
+ampersand 0x08 shift
+asterisk 0x09 shift
+parenleft 0x0a shift
+parenright 0x0b shift
+minus 0x0c
+underscore 0x0c shift
+equal 0x0d
+plus 0x0d shift
+Cyrillic_lje 0x10 altgr
+Cyrillic_LJE 0x10 shift altgr
+Cyrillic_nje 0x11 altgr
+Cyrillic_NJE 0x11 shift altgr
+Cyrillic_ie 0x12 altgr
+Cyrillic_IE 0x12 shift altgr
+Cyrillic_er 0x13 altgr
+Cyrillic_ER 0x13 shift altgr
+Cyrillic_te 0x14 altgr
+Cyrillic_TE 0x14 shift altgr
+Macedonia_dse 0x15 altgr
+Macedonia_DSE 0x15 shift altgr
+Cyrillic_u 0x16 altgr
+Cyrillic_U 0x16 shift altgr
+Cyrillic_i 0x17 altgr
+Cyrillic_I 0x17 shift altgr
+Cyrillic_o 0x18 altgr
+Cyrillic_O 0x18 shift altgr
+Cyrillic_pe 0x19 altgr
+Cyrillic_PE 0x19 shift altgr
+bracketleft 0x1a
+braceleft 0x1a shift
+Cyrillic_sha 0x1a altgr
+Cyrillic_SHA 0x1a shift altgr
+bracketright 0x1b
+braceright 0x1b shift
+Macedonia_gje 0x1b altgr
+Macedonia_GJE 0x1b shift altgr
+Cyrillic_a 0x1e altgr
+Cyrillic_A 0x1e shift altgr
+Cyrillic_es 0x1f altgr
+Cyrillic_ES 0x1f shift altgr
+Cyrillic_de 0x20 altgr
+Cyrillic_DE 0x20 shift altgr
+Cyrillic_ef 0x21 altgr
+Cyrillic_EF 0x21 shift altgr
+Cyrillic_ghe 0x22 altgr
+Cyrillic_GHE 0x22 shift altgr
+Cyrillic_ha 0x23 altgr
+Cyrillic_HA 0x23 shift altgr
+Cyrillic_je 0x24 altgr
+Cyrillic_JE 0x24 shift altgr
+Cyrillic_ka 0x25 altgr
+Cyrillic_KA 0x25 shift altgr
+Cyrillic_el 0x26 altgr
+Cyrillic_EL 0x26 shift altgr
+semicolon 0x27
+colon 0x27 shift
+Cyrillic_che 0x27 altgr
+Cyrillic_CHE 0x27 shift altgr
+apostrophe 0x28
+quotedbl 0x28 shift
+Macedonia_kje 0x28 altgr
+Macedonia_KJE 0x28 shift altgr
+grave 0x29
+asciitilde 0x29 shift
+backslash 0x2b
+bar 0x2b shift
+Cyrillic_zhe 0x2b altgr
+Cyrillic_ZHE 0x2b shift altgr
+Cyrillic_ze 0x2c altgr
+Cyrillic_ZE 0x2c shift altgr
+Cyrillic_dzhe 0x2d altgr
+Cyrillic_DZHE 0x2d shift altgr
+Cyrillic_tse 0x2e altgr
+Cyrillic_TSE 0x2e shift altgr
+Cyrillic_ve 0x2f altgr
+Cyrillic_VE 0x2f shift altgr
+Cyrillic_be 0x30 altgr
+Cyrillic_BE 0x30 shift altgr
+Cyrillic_en 0x31 altgr
+Cyrillic_EN 0x31 shift altgr
+Cyrillic_em 0x32 altgr
+Cyrillic_EM 0x32 shift altgr
+comma 0x33
+less 0x33 shift
+semicolon 0x33 shift altgr
+period 0x34
+greater 0x34 shift
+colon 0x34 shift altgr
+slash 0x35
+question 0x35 shift
--- /dev/null
+Shift_R 0x36
+Shift_L 0x2a
+
+Alt_R 0xb8
+Mode_switch 0xb8
+Alt_L 0x38
+
+Control_R 0x9d
+Control_L 0x1d
+
+# Translate Super to Windows keys.
+# This is hardcoded. See documentation for details.
+Super_R 0xdb
+Super_L 0xdc
+
+# Translate Menu to the Windows Application key.
+Menu 0xdd
--- /dev/null
+# Dutch (Netherlands)
+include common
+map 0x413
+
+exclam 0x02 shift
+onesuperior 0x02 altgr
+quotebl 0x03 shift
+twosuperior 0x03 altgr
+numbersign 0x04 shift
+threesuperior 0x04 altgr
+dollar 0x05 shift
+onequarter 0x05 altgr
+percent 0x06 shift
+onehalf 0x06 altgr
+ampersand 0x07 shift
+threequarters 0x07 altgr
+underscore 0x08 shift
+sterling 0x08 altgr
+parenleft 0x09 shift
+braceleft 0x09 altgr
+parenright 0x0a shift
+braceright 0x0a altgr
+apostrophe 0x0b shift
+slash 0x0c
+question 0x0c shift
+backslash 0x0c altgr
+degree 0x0d
+dead_tilde 0x0d shift
+dead_cedilla 0x0d altgr
+EuroSign 0x12 altgr
+paragraph 0x13 altgr
+dead_diaeresis 0x1a
+dead_circumflex 0x1a shift
+asterisk 0x1b
+bar 0x1b shift
+ssharp 0x1f altgr
+plus 0x27
+plusminus 0x27 shift
+dead_acute 0x28
+dead_grave 0x28 shift
+at 0x29
+section 0x29 shift
+notsign 0x29 altgr
+less 0x2b
+greater 0x2b shift
+guillemotleft 0x2c altgr
+guillemotright 0x2d altgr
+copyright 0x2e altgr
+mu 0x32 altgr
+comma 0x33
+semicolon 0x33 shift
+period 0x34
+colon 0x34 shift
+periodcentered 0x34 altgr
+hyphen 0x35
+equal 0x35 shift
+bracketright 0x56
+bracketleft 0x56 shift
+brokenbar 0x56 altgr
+
--- /dev/null
+# Dutch (Belgium)
+map 0x813
+include common
--- /dev/null
+# generated from XKB map no
+include common
+map 0x414
+exclam 0x02 shift
+exclamdown 0x02 altgr
+onesuperior 0x02 shift altgr
+quotedbl 0x03 shift
+at 0x03 altgr
+twosuperior 0x03 shift altgr
+numbersign 0x04 shift
+sterling 0x04 altgr
+threesuperior 0x04 shift altgr
+currency 0x05 shift
+dollar 0x05 altgr
+onequarter 0x05 shift altgr
+percent 0x06 shift
+onehalf 0x06 altgr
+cent 0x06 shift altgr
+ampersand 0x07 shift
+yen 0x07 altgr
+fiveeighths 0x07 shift altgr
+slash 0x08 shift
+braceleft 0x08 altgr
+division 0x08 shift altgr
+parenleft 0x09 shift
+bracketleft 0x09 altgr
+guillemotleft 0x09 shift altgr
+parenright 0x0a shift
+bracketright 0x0a altgr
+guillemotright 0x0a shift altgr
+equal 0x0b shift
+braceright 0x0b altgr
+degree 0x0b shift altgr
+plus 0x0c
+question 0x0c shift
+plusminus 0x0c altgr
+questiondown 0x0c shift altgr
+backslash 0x0d
+dead_grave 0x0d shift
+dead_acute 0x0d altgr
+notsign 0x0d shift altgr
+Greek_OMEGA 0x10 shift altgr
+lstroke 0x11 altgr
+Lstroke 0x11 shift altgr
+EuroSign 0x12 altgr
+cent 0x12 shift altgr
+registered 0x13 altgr
+thorn 0x14 altgr
+THORN 0x14 shift altgr
+leftarrow 0x15 altgr
+yen 0x15 shift altgr
+downarrow 0x16 altgr
+uparrow 0x16 shift altgr
+rightarrow 0x17 altgr
+idotless 0x17 shift altgr
+oe 0x18 altgr
+OE 0x18 shift altgr
+thorn 0x19 altgr
+THORN 0x19 shift altgr
+aring 0x1a
+Aring 0x1a shift
+dead_diaeresis 0x1a altgr
+dead_abovering 0x1a shift altgr
+dead_diaeresis 0x1b
+dead_circumflex 0x1b shift
+asciicircum 0x01b shift
+dead_tilde 0x1b altgr
+asciitilde 0x1b altgr
+dead_caron 0x1b shift altgr
+ordfeminine 0x1e altgr
+masculine 0x1e shift altgr
+ssharp 0x1f altgr
+section 0x1f shift altgr
+eth 0x20 altgr
+ETH 0x20 shift altgr
+dstroke 0x21 altgr
+ordfeminine 0x21 shift altgr
+eng 0x22 altgr
+ENG 0x22 shift altgr
+hstroke 0x23 altgr
+Hstroke 0x23 shift altgr
+kra 0x25 altgr
+lstroke 0x26 altgr
+Lstroke 0x26 shift altgr
+oslash 0x27
+Ooblique 0x27 shift
+dead_doubleacute 0x27 shift altgr
+ae 0x28
+AE 0x28 shift
+dead_caron 0x28 shift altgr
+bar 0x29
+section 0x29 shift
+brokenbar 0x29 altgr
+paragraph 0x29 shift altgr
+apostrophe 0x2b
+asterisk 0x2b shift
+multiply 0x2b shift altgr
+guillemotleft 0x2c altgr
+guillemotright 0x2d altgr
+copyright 0x2e altgr
+leftdoublequotemark 0x2f altgr
+rightdoublequotemark 0x30 altgr
+mu 0x32 altgr
+masculine 0x32 shift altgr
+comma 0x33
+semicolon 0x33 shift
+dead_cedilla 0x33 altgr
+dead_ogonek 0x33 shift altgr
+period 0x34
+colon 0x34 shift
+periodcentered 0x34 altgr
+dead_abovedot 0x34 shift altgr
+minus 0x35
+underscore 0x35 shift
+hyphen 0x35 altgr
+macron 0x35 shift altgr
+nobreakspace 0x39 altgr
+onehalf 0x56 altgr
+threequarters 0x56 shift altgr
--- /dev/null
+# generated from XKB map pl
+include common
+map 0x415
+exclam 0x02 shift
+onesuperior 0x02 altgr
+exclamdown 0x02 shift altgr
+at 0x03 shift
+twosuperior 0x03 altgr
+oneeighth 0x03 shift altgr
+numbersign 0x04 shift
+threesuperior 0x04 altgr
+sterling 0x04 shift altgr
+dollar 0x05 shift
+onequarter 0x05 altgr
+percent 0x06 shift
+onehalf 0x06 altgr
+threeeighths 0x06 shift altgr
+asciicircum 0x07 shift
+threequarters 0x07 altgr
+fiveeighths 0x07 shift altgr
+ampersand 0x08 shift
+braceleft 0x08 altgr
+seveneighths 0x08 shift altgr
+asterisk 0x09 shift
+bracketleft 0x09 altgr
+trademark 0x09 shift altgr
+parenleft 0x0a shift
+bracketright 0x0a altgr
+plusminus 0x0a shift altgr
+parenright 0x0b shift
+braceright 0x0b altgr
+degree 0x0b shift altgr
+minus 0x0c
+underscore 0x0c shift
+backslash 0x0c altgr
+questiondown 0x0c shift altgr
+equal 0x0d
+plus 0x0d shift
+dead_cedilla 0x0d altgr
+dead_ogonek 0x0d shift altgr
+Greek_OMEGA 0x10 shift altgr
+lstroke 0x11 altgr
+Lstroke 0x11 shift altgr
+eogonek 0x12 altgr
+Eogonek 0x12 shift altgr
+paragraph 0x13 altgr
+registered 0x13 shift altgr
+tslash 0x14 altgr
+Tslash 0x14 shift altgr
+leftarrow 0x15 altgr
+yen 0x15 shift altgr
+EuroSign 0x16 altgr
+uparrow 0x16 shift altgr
+rightarrow 0x17 altgr
+idotless 0x17 shift altgr
+oacute 0x18 altgr
+Oacute 0x18 shift altgr
+thorn 0x19 altgr
+THORN 0x19 shift altgr
+bracketleft 0x1a
+braceleft 0x1a shift
+dead_diaeresis 0x1a altgr
+dead_abovering 0x1a shift altgr
+bracketright 0x1b
+braceright 0x1b shift
+dead_tilde 0x1b altgr
+dead_macron 0x1b shift altgr
+aogonek 0x1e altgr
+Aogonek 0x1e shift altgr
+sacute 0x1f altgr
+Sacute 0x1f shift altgr
+eth 0x20 altgr
+ETH 0x20 shift altgr
+dstroke 0x21 altgr
+ordfeminine 0x21 shift altgr
+eng 0x22 altgr
+ENG 0x22 shift altgr
+hstroke 0x23 altgr
+Hstroke 0x23 shift altgr
+kra 0x25 altgr
+lstroke 0x26 altgr
+Lstroke 0x26 shift altgr
+semicolon 0x27
+colon 0x27 shift
+dead_acute 0x27 altgr
+dead_doubleacute 0x27 shift altgr
+apostrophe 0x28
+quotedbl 0x28 shift
+dead_circumflex 0x28 altgr
+dead_caron 0x28 shift altgr
+grave 0x29
+asciitilde 0x29 shift
+notsign 0x29 altgr
+backslash 0x2b
+bar 0x2b shift
+dead_grave 0x2b altgr
+dead_breve 0x2b shift altgr
+zabovedot 0x2c altgr
+Zabovedot 0x2c shift altgr
+zacute 0x2d altgr
+Zacute 0x2d shift altgr
+cacute 0x2e altgr
+Cacute 0x2e shift altgr
+leftdoublequotemark 0x2f altgr
+grave 0x2f shift altgr
+rightdoublequotemark 0x30 altgr
+nacute 0x31 altgr
+Nacute 0x31 shift altgr
+mu 0x32 altgr
+masculine 0x32 shift altgr
+comma 0x33
+less 0x33 shift
+horizconnector 0x33 altgr
+multiply 0x33 shift altgr
+period 0x34
+greater 0x34 shift
+periodcentered 0x34 altgr
+division 0x34 shift altgr
+slash 0x35
+question 0x35 shift
+dead_belowdot 0x35 altgr
+dead_abovedot 0x35 shift altgr
--- /dev/null
+# generated from XKB map pt
+include common
+map 0x816
+exclam 0x02 shift
+onesuperior 0x02 altgr
+exclamdown 0x02 shift altgr
+quotedbl 0x03 shift
+at 0x03 altgr
+oneeighth 0x03 shift altgr
+numbersign 0x04 shift
+sterling 0x04 altgr
+dollar 0x05 shift
+section 0x05 altgr
+percent 0x06 shift
+onehalf 0x06 altgr
+threeeighths 0x06 shift altgr
+ampersand 0x07 shift
+threequarters 0x07 altgr
+fiveeighths 0x07 shift altgr
+slash 0x08 shift
+braceleft 0x08 altgr
+seveneighths 0x08 shift altgr
+parenleft 0x09 shift
+bracketleft 0x09 altgr
+trademark 0x09 shift altgr
+parenright 0x0a shift
+bracketright 0x0a altgr
+plusminus 0x0a shift altgr
+equal 0x0b shift
+braceright 0x0b altgr
+degree 0x0b shift altgr
+apostrophe 0x0c
+question 0x0c shift
+backslash 0x0c altgr
+questiondown 0x0c shift altgr
+guillemotleft 0x0d
+guillemotright 0x0d shift
+dead_cedilla 0x0d altgr
+dead_ogonek 0x0d shift altgr
+Greek_OMEGA 0x10 shift altgr
+lstroke 0x11 altgr
+Lstroke 0x11 shift altgr
+EuroSign 0x12 altgr
+cent 0x12 shift altgr
+paragraph 0x13 altgr
+registered 0x13 shift altgr
+tslash 0x14 altgr
+Tslash 0x14 shift altgr
+leftarrow 0x15 altgr
+yen 0x15 shift altgr
+downarrow 0x16 altgr
+uparrow 0x16 shift altgr
+rightarrow 0x17 altgr
+idotless 0x17 shift altgr
+oslash 0x18 altgr
+Ooblique 0x18 shift altgr
+thorn 0x19 altgr
+THORN 0x19 shift altgr
+plus 0x1a
+asterisk 0x1a shift
+dead_diaeresis 0x1a altgr
+dead_abovering 0x1a shift altgr
+dead_acute 0x1b
+dead_grave 0x1b shift
+dead_tilde 0x1b altgr
+dead_macron 0x1b shift altgr
+ae 0x1e altgr
+AE 0x1e shift altgr
+ssharp 0x1f altgr
+eth 0x20 altgr
+ETH 0x20 shift altgr
+dstroke 0x21 altgr
+ordfeminine 0x21 shift altgr
+eng 0x22 altgr
+ENG 0x22 shift altgr
+hstroke 0x23 altgr
+Hstroke 0x23 shift altgr
+kra 0x25 altgr
+lstroke 0x26 altgr
+Lstroke 0x26 shift altgr
+ccedilla 0x27
+Ccedilla 0x27 shift
+dead_doubleacute 0x27 shift altgr
+masculine 0x28
+ordfeminine 0x28 shift
+dead_circumflex 0x28 altgr
+dead_caron 0x28 shift altgr
+backslash 0x29
+bar 0x29 shift
+notsign 0x29 altgr
+dead_tilde 0x2b
+dead_circumflex 0x2b shift
+dead_breve 0x2b shift altgr
+less 0x56
+greater 0x56 shift
+cent 0x2e altgr
+copyright 0x2e shift altgr
+leftdoublequotemark 0x2f altgr
+grave 0x2f shift altgr
+rightdoublequotemark 0x30 altgr
+mu 0x32 altgr
+comma 0x33
+semicolon 0x33 shift
+horizconnector 0x33 altgr
+multiply 0x33 shift altgr
+period 0x34
+colon 0x34 shift
+periodcentered 0x34 altgr
+division 0x34 shift altgr
+minus 0x35
+underscore 0x35 shift
+dead_belowdot 0x35 altgr
+dead_abovedot 0x35 shift altgr
--- /dev/null
+# generated from XKB map br
+include common
+map 0x416
+exclam 0x02 shift
+onesuperior 0x02 altgr
+exclamdown 0x02 shift altgr
+at 0x03 shift
+twosuperior 0x03 altgr
+onehalf 0x03 shift altgr
+numbersign 0x04 shift
+threesuperior 0x04 altgr
+threequarters 0x04 shift altgr
+dollar 0x05 shift
+sterling 0x05 altgr
+onequarter 0x05 shift altgr
+percent 0x06 shift
+cent 0x06 altgr
+dead_diaeresis 0x07 shift
+notsign 0x07 altgr
+diaeresis 0x07 shift altgr
+ampersand 0x08 shift
+braceleft 0x08 altgr
+asterisk 0x09 shift
+bracketleft 0x09 altgr
+parenleft 0x0a shift
+bracketright 0x0a altgr
+parenright 0x0b shift
+braceright 0x0b altgr
+minus 0x0c
+underscore 0x0c shift
+backslash 0x0c altgr
+equal 0x0d
+plus 0x0d shift
+section 0x0d altgr
+EuroSign 0x12 altgr
+registered 0x13 altgr
+dead_acute 0x1a
+dead_grave 0x1a shift
+acute 0x1a altgr
+grave 0x1a shift altgr
+bracketleft 0x1b
+braceleft 0x1b shift
+ordfeminine 0x1b altgr
+ccedilla 0x27
+Ccedilla 0x27 shift
+dead_tilde 0x28
+dead_circumflex 0x28 shift
+asciitilde 0x28 altgr
+asciicircum 0x28 shift altgr
+apostrophe 0x29
+quotedbl 0x29 shift
+bracketright 0x2b
+braceright 0x2b shift
+masculine 0x2b altgr
+copyright 0x2e altgr
+mu 0x32 altgr
+comma 0x33
+less 0x33 shift
+period 0x34
+greater 0x34 shift
+semicolon 0x35
+colon 0x35 shift
+comma 0x53 numlock
+backslash 0x56
+bar 0x56 shift
+slash 0x73
+question 0x73 shift
+degree 0x73 altgr
+KP_Decimal 0x34
--- /dev/null
+# generated from XKB map ru
+include common
+map 0x419
+exclam 0x02 shift
+at 0x03 shift
+quotedbl 0x03 shift altgr
+numbersign 0x04 shift
+dollar 0x05 shift
+asterisk 0x05 shift altgr
+percent 0x06 shift
+colon 0x06 shift altgr
+asciicircum 0x07 shift
+comma 0x07 shift altgr
+ampersand 0x08 shift
+period 0x08 shift altgr
+asterisk 0x09 shift
+semicolon 0x09 shift altgr
+parenleft 0x0a shift
+parenright 0x0b shift
+minus 0x0c
+underscore 0x0c shift
+equal 0x0d
+plus 0x0d shift
+Cyrillic_shorti 0x10 altgr
+Cyrillic_SHORTI 0x10 shift altgr
+Cyrillic_tse 0x11 altgr
+Cyrillic_TSE 0x11 shift altgr
+Cyrillic_u 0x12 altgr
+Cyrillic_U 0x12 shift altgr
+Cyrillic_ka 0x13 altgr
+Cyrillic_KA 0x13 shift altgr
+Cyrillic_ie 0x14 altgr
+Cyrillic_IE 0x14 shift altgr
+Cyrillic_en 0x15 altgr
+Cyrillic_EN 0x15 shift altgr
+Cyrillic_ghe 0x16 altgr
+Cyrillic_GHE 0x16 shift altgr
+Cyrillic_sha 0x17 altgr
+Cyrillic_SHA 0x17 shift altgr
+Cyrillic_shcha 0x18 altgr
+Cyrillic_SHCHA 0x18 shift altgr
+Cyrillic_ze 0x19 altgr
+Cyrillic_ZE 0x19 shift altgr
+bracketleft 0x1a
+braceleft 0x1a shift
+Cyrillic_ha 0x1a altgr
+Cyrillic_HA 0x1a shift altgr
+bracketright 0x1b
+braceright 0x1b shift
+Cyrillic_hardsign 0x1b altgr
+Cyrillic_HARDSIGN 0x1b shift altgr
+Cyrillic_ef 0x1e altgr
+Cyrillic_EF 0x1e shift altgr
+Cyrillic_yeru 0x1f altgr
+Cyrillic_YERU 0x1f shift altgr
+Cyrillic_ve 0x20 altgr
+Cyrillic_VE 0x20 shift altgr
+Cyrillic_a 0x21 altgr
+Cyrillic_A 0x21 shift altgr
+Cyrillic_pe 0x22 altgr
+Cyrillic_PE 0x22 shift altgr
+Cyrillic_er 0x23 altgr
+Cyrillic_ER 0x23 shift altgr
+Cyrillic_o 0x24 altgr
+Cyrillic_O 0x24 shift altgr
+Cyrillic_el 0x25 altgr
+Cyrillic_EL 0x25 shift altgr
+Cyrillic_de 0x26 altgr
+Cyrillic_DE 0x26 shift altgr
+semicolon 0x27
+colon 0x27 shift
+Cyrillic_zhe 0x27 altgr
+Cyrillic_ZHE 0x27 shift altgr
+apostrophe 0x28
+quotedbl 0x28 shift
+Cyrillic_e 0x28 altgr
+Cyrillic_E 0x28 shift altgr
+grave 0x29
+asciitilde 0x29 shift
+Cyrillic_io 0x29 altgr
+Cyrillic_IO 0x29 shift altgr
+backslash 0x2b
+bar 0x2b shift
+Cyrillic_ya 0x2c altgr
+Cyrillic_YA 0x2c shift altgr
+Cyrillic_che 0x2d altgr
+Cyrillic_CHE 0x2d shift altgr
+Cyrillic_es 0x2e altgr
+Cyrillic_ES 0x2e shift altgr
+Cyrillic_em 0x2f altgr
+Cyrillic_EM 0x2f shift altgr
+Cyrillic_i 0x30 altgr
+Cyrillic_I 0x30 shift altgr
+Cyrillic_te 0x31 altgr
+Cyrillic_TE 0x31 shift altgr
+Cyrillic_softsign 0x32 altgr
+Cyrillic_SOFTSIGN 0x32 shift altgr
+comma 0x33
+less 0x33 shift
+Cyrillic_be 0x33 altgr
+Cyrillic_BE 0x33 shift altgr
+period 0x34
+greater 0x34 shift
+Cyrillic_yu 0x34 altgr
+Cyrillic_YU 0x34 shift altgr
+slash 0x35
+question 0x35 shift
+slash 0x56 altgr
+bar 0x56 shift altgr
--- /dev/null
+# generated from XKB map sl
+include common
+map 0x424
+exclam 0x02 shift
+asciitilde 0x02 altgr
+dead_tilde 0x02 shift altgr
+quotedbl 0x03 shift
+dead_caron 0x03 altgr
+caron 0x03 shift altgr
+numbersign 0x04 shift
+asciicircum 0x04 altgr
+dead_circumflex 0x04 shift altgr
+dollar 0x05 shift
+dead_breve 0x05 altgr
+breve 0x05 shift altgr
+percent 0x06 shift
+degree 0x06 altgr
+dead_abovering 0x06 shift altgr
+ampersand 0x07 shift
+dead_ogonek 0x07 altgr
+ogonek 0x07 shift altgr
+slash 0x08 shift
+grave 0x08 altgr
+dead_grave 0x08 shift altgr
+parenleft 0x09 shift
+dead_abovedot 0x09 altgr
+abovedot 0x09 shift altgr
+parenright 0x0a shift
+dead_acute 0x0a altgr
+equal 0x0b shift
+dead_doubleacute 0x0b altgr
+doubleacute 0x0b shift altgr
+apostrophe 0x0c
+question 0x0c shift
+dead_diaeresis 0x0c altgr
+diaeresis 0x0c shift altgr
+plus 0x0d
+asterisk 0x0d shift
+dead_cedilla 0x0d altgr
+cedilla 0x0d shift altgr
+backslash 0x10 altgr
+Greek_OMEGA 0x10 shift altgr
+bar 0x11 altgr
+Lstroke 0x11 shift altgr
+EuroSign 0x12 altgr
+paragraph 0x13 altgr
+registered 0x13 shift altgr
+tslash 0x14 altgr
+Tslash 0x14 shift altgr
+z 0x15 addupper
+leftarrow 0x15 altgr
+yen 0x15 shift altgr
+downarrow 0x16 altgr
+uparrow 0x16 shift altgr
+rightarrow 0x17 altgr
+idotless 0x17 shift altgr
+oslash 0x18 altgr
+Ooblique 0x18 shift altgr
+thorn 0x19 altgr
+THORN 0x19 shift altgr
+scaron 0x1a
+Scaron 0x1a shift
+division 0x1a altgr
+dstroke 0x1b
+Dstroke 0x1b shift
+multiply 0x1b altgr
+dead_macron 0x1b shift altgr
+ae 0x1e altgr
+AE 0x1e shift altgr
+ssharp 0x1f altgr
+section 0x1f shift altgr
+eth 0x20 altgr
+ETH 0x20 shift altgr
+bracketleft 0x21 altgr
+ordfeminine 0x21 shift altgr
+bracketright 0x22 altgr
+ENG 0x22 shift altgr
+hstroke 0x23 altgr
+Hstroke 0x23 shift altgr
+lstroke 0x25 altgr
+Lstroke 0x26 altgr
+ccaron 0x27
+Ccaron 0x27 shift
+cacute 0x28
+Cacute 0x28 shift
+ssharp 0x28 altgr
+dead_cedilla 0x29
+notsign 0x29 altgr
+zcaron 0x2b
+Zcaron 0x2b shift
+currency 0x2b altgr
+y 0x2c addupper
+guillemotleft 0x2c altgr
+guillemotright 0x2d altgr
+cent 0x2e altgr
+copyright 0x2e shift altgr
+at 0x2f altgr
+braceleft 0x30 altgr
+braceright 0x31 altgr
+section 0x32 altgr
+masculine 0x32 shift altgr
+comma 0x33
+semicolon 0x33 shift
+horizconnector 0x33 altgr
+period 0x34
+colon 0x34 shift
+periodcentered 0x34 altgr
+minus 0x35
+underscore 0x35 shift
+dead_belowdot 0x35 altgr
--- /dev/null
+map 0x0000041d
+include common
+
+#
+# Top row
+#
+section 0x29
+onehalf 0x29 shift
+
+# 1
+exclam 0x2 shift
+
+# 2
+quotedbl 0x3 shift
+at 0x3 altgr
+
+# 3
+numbersign 0x4 shift
+sterling 0x4 altgr
+# 4
+currency 0x5 shift
+dollar 0x5 altgr
+# 5
+percent 0x6 shift
+# 6
+ampersand 0x7 shift
+# 7
+slash 0x8 shift
+braceleft 0x8 altgr
+# 8
+parenleft 0x9 shift
+bracketleft 0x9 altgr
+# 9
+parenright 0xa shift
+bracketright 0xa altgr
+# 0
+equal 0xb shift
+braceright 0xb altgr
+
+plus 0xc
+question 0xc shift
+backslash 0xc altgr
+
+acute 0xd
+dead_acute 0xd
+grave 0xd shift
+dead_grave 0xd shift
+
+#
+# QWERTY first row
+#
+EuroSign 0x12 altgr
+aring 0x1a
+Aring 0x1a shift
+dead_diaeresis 0x1b
+dead_circumflex 0x1b shift
+dead_tilde 0x1b altgr
+
+#
+# QWERTY second row
+#
+odiaeresis 0x27
+Odiaeresis 0x27 shift
+adiaeresis 0x28
+Adiaeresis 0x28 shift
+apostrophe 0x2b
+asterisk 0x2b shift
+
+#
+# QWERTY third row
+#
+less 0x56
+greater 0x56 shift
+bar 0x56 altgr
+mu 0x32 altgr
+comma 0x33
+semicolon 0x33 shift
+period 0x34
+colon 0x34 shift
+minus 0x35
+underscore 0x35 shift
+
--- /dev/null
+# generated from XKB map th
+include common
+map 0x41e
+exclam 0x02 shift
+Thai_lakkhangyao 0x02 altgr
+plus 0x02 shift altgr
+at 0x03 shift
+slash 0x03 altgr
+Thai_leknung 0x03 shift altgr
+numbersign 0x04 shift
+minus 0x04 altgr
+Thai_leksong 0x04 shift altgr
+dollar 0x05 shift
+Thai_phosamphao 0x05 altgr
+Thai_leksam 0x05 shift altgr
+percent 0x06 shift
+Thai_thothung 0x06 altgr
+Thai_leksi 0x06 shift altgr
+asciicircum 0x07 shift
+Thai_sarau 0x07 altgr
+Thai_sarauu 0x07 shift altgr
+ampersand 0x08 shift
+Thai_saraue 0x08 altgr
+Thai_baht 0x08 shift altgr
+asterisk 0x09 shift
+Thai_khokhwai 0x09 altgr
+Thai_lekha 0x09 shift altgr
+parenleft 0x0a shift
+Thai_totao 0x0a altgr
+Thai_lekhok 0x0a shift altgr
+parenright 0x0b shift
+Thai_chochan 0x0b altgr
+Thai_lekchet 0x0b shift altgr
+minus 0x0c
+underscore 0x0c shift
+Thai_khokhai 0x0c altgr
+Thai_lekpaet 0x0c shift altgr
+equal 0x0d
+plus 0x0d shift
+Thai_chochang 0x0d altgr
+Thai_lekkao 0x0d shift altgr
+Thai_maiyamok 0x10 altgr
+Thai_leksun 0x10 shift altgr
+Thai_saraaimaimalai 0x11 altgr
+quotedbl 0x11 shift altgr
+Thai_saraam 0x12 altgr
+Thai_dochada 0x12 shift altgr
+Thai_phophan 0x13 altgr
+Thai_thonangmontho 0x13 shift altgr
+Thai_saraa 0x14 altgr
+Thai_thothong 0x14 shift altgr
+Thai_maihanakat 0x15 altgr
+Thai_nikhahit 0x15 shift altgr
+Thai_saraii 0x16 altgr
+Thai_maitri 0x16 shift altgr
+Thai_rorua 0x17 altgr
+Thai_nonen 0x17 shift altgr
+Thai_nonu 0x18 altgr
+Thai_paiyannoi 0x18 shift altgr
+Thai_yoyak 0x19 altgr
+Thai_yoying 0x19 shift altgr
+bracketleft 0x1a
+braceleft 0x1a shift
+Thai_bobaimai 0x1a altgr
+Thai_thothan 0x1a shift altgr
+bracketright 0x1b
+braceright 0x1b shift
+Thai_loling 0x1b altgr
+comma 0x1b shift altgr
+Thai_fofan 0x1e altgr
+Thai_ru 0x1e shift altgr
+Thai_hohip 0x1f altgr
+Thai_khorakhang 0x1f shift altgr
+Thai_kokai 0x20 altgr
+Thai_topatak 0x20 shift altgr
+Thai_dodek 0x21 altgr
+Thai_sarao 0x21 shift altgr
+Thai_sarae 0x22 altgr
+Thai_chochoe 0x22 shift altgr
+Thai_maitho 0x23 altgr
+Thai_maitaikhu 0x23 shift altgr
+Thai_maiek 0x24 altgr
+Thai_maichattawa 0x24 shift altgr
+Thai_saraaa 0x25 altgr
+Thai_sorusi 0x25 shift altgr
+Thai_sosua 0x26 altgr
+Thai_sosala 0x26 shift altgr
+semicolon 0x27
+colon 0x27 shift
+Thai_wowaen 0x27 altgr
+Thai_soso 0x27 shift altgr
+apostrophe 0x28
+quotedbl 0x28 shift
+Thai_ngongu 0x28 altgr
+period 0x28 shift altgr
+grave 0x29
+asciitilde 0x29 shift
+underscore 0x29 altgr
+percent 0x29 shift altgr
+ISO_First_Group 0x2a shift
+backslash 0x2b
+bar 0x2b shift
+Thai_khokhuat 0x2b altgr
+Thai_khokhon 0x2b shift altgr
+Thai_phophung 0x2c altgr
+parenleft 0x2c shift altgr
+Thai_popla 0x2d altgr
+parenright 0x2d shift altgr
+Thai_saraae 0x2e altgr
+Thai_choching 0x2e shift altgr
+Thai_oang 0x2f altgr
+Thai_honokhuk 0x2f shift altgr
+Thai_sarai 0x30 altgr
+Thai_phinthu 0x30 shift altgr
+Thai_sarauee 0x31 altgr
+Thai_thanthakhat 0x31 shift altgr
+Thai_thothahan 0x32 altgr
+question 0x32 shift altgr
+comma 0x33
+less 0x33 shift
+Thai_moma 0x33 altgr
+Thai_thophuthao 0x33 shift altgr
+period 0x34
+greater 0x34 shift
+Thai_saraaimaimuan 0x34 altgr
+Thai_lochula 0x34 shift altgr
+slash 0x35
+question 0x35 shift
+Thai_fofa 0x35 altgr
+Thai_lu 0x35 shift altgr
+ISO_Last_Group 0x36 shift
--- /dev/null
+# generated from XKB map tr
+include common
+map 0x41f
+exclam 0x02 shift
+onesuperior 0x02 altgr
+exclamdown 0x02 shift altgr
+apostrophe 0x03 shift
+at 0x03 altgr
+oneeighth 0x03 shift altgr
+dead_circumflex 0x04 shift
+numbersign 0x04 altgr
+sterling 0x04 shift altgr
+plus 0x05 shift
+dollar 0x05 altgr
+percent 0x06 shift
+onehalf 0x06 altgr
+threeeighths 0x06 shift altgr
+ampersand 0x07 shift
+asciicircum 0x07 altgr
+fiveeighths 0x07 shift altgr
+slash 0x08 shift
+braceleft 0x08 altgr
+seveneighths 0x08 shift altgr
+parenleft 0x09 shift
+bracketleft 0x09 altgr
+trademark 0x09 shift altgr
+parenright 0x0a shift
+bracketright 0x0a altgr
+plusminus 0x0a shift altgr
+equal 0x0b shift
+braceright 0x0b altgr
+degree 0x0b shift altgr
+asterisk 0x0c
+question 0x0c shift
+backslash 0x0c altgr
+questiondown 0x0c shift altgr
+minus 0x0d
+underscore 0x0d shift
+dead_cedilla 0x0d altgr
+dead_ogonek 0x0d shift altgr
+at 0x10 altgr
+Greek_OMEGA 0x10 shift altgr
+lstroke 0x11 altgr
+Lstroke 0x11 shift altgr
+EuroSign 0x12 altgr
+paragraph 0x13 altgr
+registered 0x13 shift altgr
+tslash 0x14 altgr
+Tslash 0x14 shift altgr
+leftarrow 0x15 altgr
+yen 0x15 shift altgr
+downarrow 0x16 altgr
+uparrow 0x16 shift altgr
+idotless 0x17
+I 0x17 shift
+rightarrow 0x17 altgr
+oslash 0x18 altgr
+Ooblique 0x18 shift altgr
+thorn 0x19 altgr
+THORN 0x19 shift altgr
+gbreve 0x1a
+Gbreve 0x1a shift
+dead_diaeresis 0x1a altgr
+dead_abovering 0x1a shift altgr
+udiaeresis 0x1b
+Udiaeresis 0x1b shift
+asciitilde 0x1b altgr
+dead_macron 0x1b shift altgr
+ae 0x1e altgr
+AE 0x1e shift altgr
+ssharp 0x1f altgr
+section 0x1f shift altgr
+eth 0x20 altgr
+ETH 0x20 shift altgr
+dstroke 0x21 altgr
+ordfeminine 0x21 shift altgr
+eng 0x22 altgr
+ENG 0x22 shift altgr
+hstroke 0x23 altgr
+Hstroke 0x23 shift altgr
+kra 0x25 altgr
+ampersand 0x25 shift altgr
+lstroke 0x26 altgr
+Lstroke 0x26 shift altgr
+scedilla 0x27
+Scedilla 0x27 shift
+dead_acute 0x27 altgr
+dead_doubleacute 0x27 shift altgr
+i 0x28
+Iabovedot 0x28 shift
+dead_circumflex 0x28 altgr
+dead_caron 0x28 shift altgr
+backslash 0x29
+quotedbl 0x29 shift
+asciitilde 0x29 altgr
+comma 0x2b
+semicolon 0x2b shift
+bar 0x2b altgr
+dead_breve 0x2b shift altgr
+guillemotleft 0x2c altgr
+less 0x2c shift altgr
+guillemotright 0x2d altgr
+greater 0x2d shift altgr
+cent 0x2e altgr
+copyright 0x2e shift altgr
+leftdoublequotemark 0x2f altgr
+grave 0x2f shift altgr
+rightdoublequotemark 0x30 altgr
+apostrophe 0x30 shift altgr
+mu 0x32 altgr
+masculine 0x32 shift altgr
+odiaeresis 0x33
+Odiaeresis 0x33 shift
+less 0x33 altgr
+multiply 0x33 shift altgr
+ccedilla 0x34
+Ccedilla 0x34 shift
+greater 0x34 altgr
+division 0x34 shift altgr
+period 0x35
+colon 0x35 shift
+dead_belowdot 0x35 altgr
+dead_abovedot 0x35 shift altgr
--- /dev/null
+/*
+ * qemu user main
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include "qemu.h"
+
+#define DEBUG_LOGFILE "/tmp/qemu.log"
+
+#ifdef __APPLE__
+#include <crt_externs.h>
+# define environ (*_NSGetEnviron())
+#endif
+
+static const char *interp_prefix = CONFIG_QEMU_PREFIX;
+
+#if defined(__i386__) && !defined(CONFIG_STATIC)
+/* Force usage of an ELF interpreter even if it is an ELF shared
+ object ! */
+const char interp[] __attribute__((section(".interp"))) = "/lib/ld-linux.so.2";
+#endif
+
+/* for recent libc, we add these dummy symbols which are not declared
+ when generating a linked object (bug in ld ?) */
+#if (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 3)) && !defined(CONFIG_STATIC)
+long __preinit_array_start[0];
+long __preinit_array_end[0];
+long __init_array_start[0];
+long __init_array_end[0];
+long __fini_array_start[0];
+long __fini_array_end[0];
+#endif
+
+/* XXX: on x86 MAP_GROWSDOWN only works if ESP <= address + 32, so
+ we allocate a bigger stack. Need a better solution, for example
+ by remapping the process stack directly at the right place */
+unsigned long x86_stack_size = 512 * 1024;
+
+void gemu_log(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+}
+/* timers for rdtsc */
+
+#if defined(__i386__)
+
+int64_t cpu_get_real_ticks(void)
+{
+ int64_t val;
+ asm volatile ("rdtsc" : "=A" (val));
+ return val;
+}
+
+#elif defined(__x86_64__)
+
+int64_t cpu_get_real_ticks(void)
+{
+ uint32_t low,high;
+ int64_t val;
+ asm volatile("rdtsc" : "=a" (low), "=d" (high));
+ val = high;
+ val <<= 32;
+ val |= low;
+ return val;
+}
+
+#else
+
+static uint64_t emu_time;
+
+int64_t cpu_get_real_ticks(void)
+{
+ return emu_time++;
+}
+
+#endif
+
+#ifdef TARGET_I386
+/***********************************************************/
+/* CPUX86 core interface */
+
+uint64_t cpu_get_tsc(CPUX86State *env)
+{
+ return cpu_get_real_ticks();
+}
+
+void cpu_loop()
+{
+}
+#endif
+
+void usage(void)
+{
+ printf("qemu-" TARGET_ARCH " version " QEMU_VERSION ", Copyright (c) 2003-2004 Fabrice Bellard\n"
+ "usage: qemu-" TARGET_ARCH " [-h] [-d opts] [-L path] [-s size] program [arguments...]\n"
+ "Linux CPU emulator (compiled for %s emulation)\n"
+ "\n"
+ "-h print this help\n"
+ "-L path set the elf interpreter prefix (default=%s)\n"
+ "-s size set the stack size in bytes (default=%ld)\n"
+ "\n"
+ "debug options:\n"
+#ifdef USE_CODE_COPY
+ "-no-code-copy disable code copy acceleration\n"
+#endif
+ "-l options activate log (logfile=%s)\n"
+ "-p xen port number\n",
+ "-d xen domain id\n",
+ TARGET_ARCH,
+ interp_prefix,
+ x86_stack_size,
+ DEBUG_LOGFILE);
+ _exit(1);
+}
+
+/* XXX: currently only used for async signals (see signal.c) */
+CPUState *global_env;
+/* used only if single thread */
+CPUState *cpu_single_env = NULL;
+
+/* used to free thread contexts */
+TaskState *first_task_state;
+
+int main(int argc, char **argv)
+{
+ const char *filename;
+ struct target_pt_regs regs1, *regs = ®s1;
+ struct image_info info1, *info = &info1;
+ TaskState ts1, *ts = &ts1;
+ CPUState *env;
+ int optind;
+ const char *r;
+
+ if (argc <= 1)
+ usage();
+
+ /* init debug */
+ cpu_set_log_filename(DEBUG_LOGFILE);
+ cpu_set_log(0);
+
+ optind = 1;
+ for(;;) {
+ if (optind >= argc)
+ break;
+ r = argv[optind];
+ if (r[0] != '-')
+ break;
+ optind++;
+ r++;
+ if (!strcmp(r, "-")) {
+ break;
+ } else if (!strcmp(r, "l")) {
+ int mask;
+ CPULogItem *item;
+
+ if (optind >= argc)
+ break;
+
+ r = argv[optind++];
+ mask = cpu_str_to_log_mask(r);
+ if (!mask) {
+ printf("Log items (comma separated):\n");
+ for(item = cpu_log_items; item->mask != 0; item++) {
+ printf("%-10s %s\n", item->name, item->help);
+ }
+ exit(1);
+ }
+ cpu_set_log(mask);
+ } else if (!strcmp(r, "s")) {
+ r = argv[optind++];
+ x86_stack_size = strtol(r, (char **)&r, 0);
+ if (x86_stack_size <= 0)
+ usage();
+ if (*r == 'M')
+ x86_stack_size *= 1024 * 1024;
+ else if (*r == 'k' || *r == 'K')
+ x86_stack_size *= 1024;
+ } else if (!strcmp(r, "L")) {
+ interp_prefix = argv[optind++];
+ } else if (!strcmp(r, "p")) {
+ qemu_host_page_size = atoi(argv[optind++]);
+ if (qemu_host_page_size == 0 ||
+ (qemu_host_page_size & (qemu_host_page_size - 1)) != 0) {
+ fprintf(stderr, "page size must be a power of two\n");
+ exit(1);
+ }
+ } else
+#ifdef USE_CODE_COPY
+ if (!strcmp(r, "no-code-copy")) {
+ code_copy_enabled = 0;
+ } else
+#endif
+ {
+ usage();
+ }
+ }
+ if (optind >= argc)
+ usage();
+ filename = argv[optind];
+
+ /* Zero out regs */
+ memset(regs, 0, sizeof(struct target_pt_regs));
+
+ /* Zero out image_info */
+ memset(info, 0, sizeof(struct image_info));
+
+ /* Scan interp_prefix dir for replacement files. */
+ init_paths(interp_prefix);
+
+ /* NOTE: we need to init the CPU at this stage to get
+ qemu_host_page_size */
+ env = cpu_init();
+
+ global_env = env;
+
+ /* build Task State */
+ memset(ts, 0, sizeof(TaskState));
+ env->opaque = ts;
+ ts->used = 1;
+ env->user_mode_only = 1;
+
+ cpu_loop(env);
+ /* never exits */
+ return 0;
+}
+++ /dev/null
-TOPDIR= ..
-CXXFLAGS=-I. -I../include -I..
-OBJS= memory.o misc_mem.o
-
-all: libmemory.a
-
-libmemory.a: $(OBJS)
- $(AR) $(ARFLAGS) $@ $(OBJS)
-
-include $(TOPDIR)/mk/helix.mk
-
-install:: all
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: memory.cc,v 1.27 2003/03/02 23:59:12 cbothamy Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2001 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-
-
-
-
-
-#include "bochs.h"
-#define LOG_THIS BX_MEM_THIS
-
-#if BX_PROVIDE_CPU_MEMORY
-
- void BX_CPP_AttrRegparmN(3)
-BX_MEM_C::writePhysicalPage(BX_CPU_C *cpu, dma_addr_t addr, unsigned len, void *data)
-{
- Bit8u *data_ptr;
- Bit32u a20addr;
-
- // Note: accesses should always be contained within a single page now.
-
-#if BX_IODEBUG_SUPPORT
- bx_iodebug_c::mem_write(cpu, addr, len, data);
-#endif
- if (addr+len > this->dma_limit)
- BX_PANIC(("address too large: %lx > %lx", addr+len, this->dma_limit));
-
- a20addr = A20ADDR(addr);
- BX_INSTR_PHY_WRITE(cpu->which_cpu(), a20addr, len);
-
-#if BX_DEBUGGER
- // (mch) Check for physical write break points, TODO
- // (bbd) Each breakpoint should have an associated CPU#, TODO
- for (int i = 0; i < num_write_watchpoints; i++)
- if (write_watchpoint[i] == a20addr) {
- BX_CPU(0)->watchpoint = a20addr;
- BX_CPU(0)->break_point = BREAK_POINT_WRITE;
- break;
- }
-#endif
-
-#if BX_SupportICache
- if (a20addr < BX_MEM_THIS len)
- cpu->iCache.decWriteStamp(cpu, a20addr);
-#endif
-
- if ( a20addr <= BX_MEM_THIS len ) {
- // all of data is within limits of physical memory
- if ( (a20addr & 0xfff80000) != 0x00080000 ) {
- if (len == 4) {
- WriteHostDWordToLittleEndian(&vector[a20addr], *(Bit32u*)data);
- BX_DBG_DIRTY_PAGE(a20addr >> 12);
- return;
- }
- if (len == 2) {
- WriteHostWordToLittleEndian(&vector[a20addr], *(Bit16u*)data);
- BX_DBG_DIRTY_PAGE(a20addr >> 12);
- return;
- }
- if (len == 1) {
- * ((Bit8u *) (&vector[a20addr])) = * (Bit8u *) data;
- BX_DBG_DIRTY_PAGE(a20addr >> 12);
- return;
- }
- // len == other, just fall thru to special cases handling
- }
-
-#ifdef BX_LITTLE_ENDIAN
- data_ptr = (Bit8u *) data;
-#else // BX_BIG_ENDIAN
- data_ptr = (Bit8u *) data + (len - 1);
-#endif
-
-write_one:
- if ( (a20addr & 0xfff80000) != 0x00080000 ) {
- // addr *not* in range 00080000 .. 000FFFFF
- vector[a20addr] = *data_ptr;
- BX_DBG_DIRTY_PAGE(a20addr >> 12);
-inc_one:
- if (len == 1) return;
- len--;
- a20addr++;
-#ifdef BX_LITTLE_ENDIAN
- data_ptr++;
-#else // BX_BIG_ENDIAN
- data_ptr--;
-#endif
- goto write_one;
- }
-
- // addr in range 00080000 .. 000FFFFF
-
- if (a20addr <= 0x0009ffff) {
- // regular memory 80000 .. 9FFFF
- vector[a20addr] = *data_ptr;
- BX_DBG_DIRTY_PAGE(a20addr >> 12);
- goto inc_one;
- }
- if (a20addr <= 0x000bffff) {
- // VGA memory A0000 .. BFFFF
- DEV_vga_mem_write(a20addr, *data_ptr);
- BX_DBG_DIRTY_PAGE(a20addr >> 12);
- BX_DBG_UCMEM_REPORT(a20addr, 1, BX_WRITE, *data_ptr); // obsolete
- goto inc_one;
- }
- // adapter ROM C0000 .. DFFFF
- // ROM BIOS memory E0000 .. FFFFF
- // (ignore write)
- //BX_INFO(("ROM lock %08x: len=%u",
- // (unsigned) a20addr, (unsigned) len));
-#if BX_PCI_SUPPORT == 0
-#if BX_SHADOW_RAM
- // Write it since its in shadow RAM
- vector[a20addr] = *data_ptr;
- BX_DBG_DIRTY_PAGE(a20addr >> 12);
-#else
- // ignore write to ROM
-#endif
-#else
- // Write Based on 440fx Programming
- if (bx_options.Oi440FXSupport->get () &&
- ((a20addr >= 0xC0000) && (a20addr <= 0xFFFFF))) {
- switch (DEV_pci_wr_memtype(a20addr & 0xFC000)) {
- case 0x1: // Writes to ShadowRAM
-// BX_INFO(("Writing to ShadowRAM %08x, len %u ! ", (unsigned) a20addr, (unsigned) len));
- shadow[a20addr - 0xc0000] = *data_ptr;
- BX_DBG_DIRTY_PAGE(a20addr >> 12);
- goto inc_one;
-
- case 0x0: // Writes to ROM, Inhibit
- BX_DEBUG(("Write to ROM ignored: address %08x, data %02x", (unsigned) a20addr, *data_ptr));
- goto inc_one;
- default:
- BX_PANIC(("writePhysicalPage: default case"));
- goto inc_one;
- }
- }
-#endif
- goto inc_one;
- }
-
- else {
- // some or all of data is outside limits of physical memory
- unsigned i;
-
-#ifdef BX_LITTLE_ENDIAN
- data_ptr = (Bit8u *) data;
-#else // BX_BIG_ENDIAN
- data_ptr = (Bit8u *) data + (len - 1);
-#endif
-
-
-#if BX_SUPPORT_VBE
- // Check VBE LFB support
-
- if ((a20addr >= VBE_DISPI_LFB_PHYSICAL_ADDRESS) &&
- (a20addr < (VBE_DISPI_LFB_PHYSICAL_ADDRESS + VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES)))
- {
- for (i = 0; i < len; i++) {
-
- //if (a20addr < BX_MEM_THIS len) {
- //vector[a20addr] = *data_ptr;
- //BX_DBG_DIRTY_PAGE(a20addr >> 12);
- DEV_vga_mem_write(a20addr, *data_ptr);
- // }
-
- // otherwise ignore byte, since it overruns memory
- addr++;
- a20addr = (addr);
-#ifdef BX_LITTLE_ENDIAN
- data_ptr++;
-#else // BX_BIG_ENDIAN
- data_ptr--;
-#endif
- }
- return;
- }
-
-#endif
-
-
-#if BX_SUPPORT_APIC
- bx_generic_apic_c *local_apic = &cpu->local_apic;
- bx_generic_apic_c *ioapic = bx_devices.ioapic;
- if (local_apic->is_selected (a20addr, len)) {
- local_apic->write (a20addr, (Bit32u *)data, len);
- return;
- } else if (ioapic->is_selected (a20addr, len)) {
- ioapic->write (a20addr, (Bit32u *)data, len);
- return;
- }
- else
-#endif
- for (i = 0; i < len; i++) {
- if (a20addr < BX_MEM_THIS len) {
- vector[a20addr] = *data_ptr;
- BX_DBG_DIRTY_PAGE(a20addr >> 12);
- }
- // otherwise ignore byte, since it overruns memory
- addr++;
- a20addr = (addr);
-#ifdef BX_LITTLE_ENDIAN
- data_ptr++;
-#else // BX_BIG_ENDIAN
- data_ptr--;
-#endif
- }
- return;
- }
-}
-
-
- void BX_CPP_AttrRegparmN(3)
-BX_MEM_C::readPhysicalPage(BX_CPU_C *cpu, dma_addr_t addr, unsigned len, void *data)
-{
- Bit8u *data_ptr;
- Bit32u a20addr;
-
-#if BX_IODEBUG_SUPPORT
- bx_iodebug_c::mem_read(cpu, addr, len, data);
-#endif
-
- if (addr+len > this->dma_limit)
- BX_PANIC(("address too large: %lx > %lx", addr+len, this->dma_limit));
-
- a20addr = A20ADDR(addr);
- BX_INSTR_PHY_READ(cpu->which_cpu(), a20addr, len);
-
-#if BX_DEBUGGER
- // (mch) Check for physical read break points, TODO
- // (bbd) Each breakpoint should have an associated CPU#, TODO
- for (int i = 0; i < num_read_watchpoints; i++)
- if (read_watchpoint[i] == a20addr) {
- BX_CPU(0)->watchpoint = a20addr;
- BX_CPU(0)->break_point = BREAK_POINT_READ;
- break;
- }
-#endif
-
- if ( (a20addr + len) <= BX_MEM_THIS len ) {
- // all of data is within limits of physical memory
- if ( (a20addr & 0xfff80000) != 0x00080000 ) {
- if (len == 4) {
- ReadHostDWordFromLittleEndian(&vector[a20addr], * (Bit32u*) data);
- return;
- }
- if (len == 2) {
- ReadHostWordFromLittleEndian(&vector[a20addr], * (Bit16u*) data);
- return;
- }
- if (len == 1) {
- * (Bit8u *) data = * ((Bit8u *) (&vector[a20addr]));
- return;
- }
- // len == 3 case can just fall thru to special cases handling
- }
-
-
-#ifdef BX_LITTLE_ENDIAN
- data_ptr = (Bit8u *) data;
-#else // BX_BIG_ENDIAN
- data_ptr = (Bit8u *) data + (len - 1);
-#endif
-
-
-
-read_one:
- if ( (a20addr & 0xfff80000) != 0x00080000 ) {
- // addr *not* in range 00080000 .. 000FFFFF
- *data_ptr = vector[a20addr];
-inc_one:
- if (len == 1) return;
- len--;
- a20addr++;
-#ifdef BX_LITTLE_ENDIAN
- data_ptr++;
-#else // BX_BIG_ENDIAN
- data_ptr--;
-#endif
- goto read_one;
- }
-
- // addr in range 00080000 .. 000FFFFF
-#if BX_PCI_SUPPORT == 0
- if ((a20addr <= 0x0009ffff) || (a20addr >= 0x000c0000) ) {
- // regular memory 80000 .. 9FFFF, C0000 .. F0000
- *data_ptr = vector[a20addr];
- goto inc_one;
- }
- // VGA memory A0000 .. BFFFF
- *data_ptr = DEV_vga_mem_read(a20addr);
- BX_DBG_UCMEM_REPORT(a20addr, 1, BX_READ, *data_ptr); // obsolete
- goto inc_one;
-#else // #if BX_PCI_SUPPORT == 0
- if (a20addr <= 0x0009ffff) {
- *data_ptr = vector[a20addr];
- goto inc_one;
- }
- if (a20addr <= 0x000BFFFF) {
- // VGA memory A0000 .. BFFFF
- *data_ptr = DEV_vga_mem_read(a20addr);
- BX_DBG_UCMEM_REPORT(a20addr, 1, BX_READ, *data_ptr);
- goto inc_one;
- }
-
- // a20addr in C0000 .. FFFFF
- if (!bx_options.Oi440FXSupport->get ()) {
- *data_ptr = vector[a20addr];
- goto inc_one;
- }
- else {
- switch (DEV_pci_rd_memtype(a20addr & 0xFC000)) {
- case 0x1: // Read from ShadowRAM
- *data_ptr = shadow[a20addr - 0xc0000];
- BX_INFO(("Reading from ShadowRAM %08x, Data %02x ", (unsigned) a20addr, *data_ptr));
- goto inc_one;
-
- case 0x0: // Read from ROM
- *data_ptr = vector[a20addr];
- //BX_INFO(("Reading from ROM %08x, Data %02x ", (unsigned) a20addr, *data_ptr));
- goto inc_one;
- default:
- BX_PANIC(("::readPhysicalPage: default case"));
- }
- }
- goto inc_one;
-#endif // #if BX_PCI_SUPPORT == 0
- }
- else {
- // some or all of data is outside limits of physical memory
- unsigned i;
-
-#ifdef BX_LITTLE_ENDIAN
- data_ptr = (Bit8u *) data;
-#else // BX_BIG_ENDIAN
- data_ptr = (Bit8u *) data + (len - 1);
-#endif
-
-#if BX_SUPPORT_VBE
- // Check VBE LFB support
-
- if ((a20addr >= VBE_DISPI_LFB_PHYSICAL_ADDRESS) &&
- (a20addr < (VBE_DISPI_LFB_PHYSICAL_ADDRESS + VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES)))
- {
- for (i = 0; i < len; i++) {
-
- //if (a20addr < BX_MEM_THIS len) {
- //vector[a20addr] = *data_ptr;
- //BX_DBG_DIRTY_PAGE(a20addr >> 12);
- *data_ptr = DEV_vga_mem_read(a20addr);
- // }
-
- // otherwise ignore byte, since it overruns memory
- addr++;
- a20addr = (addr);
-#ifdef BX_LITTLE_ENDIAN
- data_ptr++;
-#else // BX_BIG_ENDIAN
- data_ptr--;
-#endif
- }
- return;
- }
-
-#endif
-
-
-#if BX_SUPPORT_APIC
- bx_generic_apic_c *local_apic = &cpu->local_apic;
- bx_generic_apic_c *ioapic = bx_devices.ioapic;
- if (local_apic->is_selected (addr, len)) {
- local_apic->read (addr, data, len);
- return;
- } else if (ioapic->is_selected (addr, len)) {
- ioapic->read (addr, data, len);
- return;
- }
-#endif
- for (i = 0; i < len; i++) {
-#if BX_PCI_SUPPORT == 0
- if (a20addr < BX_MEM_THIS len)
- *data_ptr = vector[a20addr];
- else
- *data_ptr = 0xff;
-#else // BX_PCI_SUPPORT == 0
- if (a20addr < BX_MEM_THIS len) {
- if ((a20addr >= 0x000C0000) && (a20addr <= 0x000FFFFF)) {
- if (!bx_options.Oi440FXSupport->get ())
- *data_ptr = vector[a20addr];
- else {
- switch (DEV_pci_rd_memtype(a20addr & 0xFC000)) {
- case 0x0: // Read from ROM
- *data_ptr = vector[a20addr];
- //BX_INFO(("Reading from ROM %08x, Data %02x ", (unsigned) a20addr, *data_ptr));
- break;
-
- case 0x1: // Read from Shadow RAM
- *data_ptr = shadow[a20addr - 0xc0000];
- BX_INFO(("Reading from ShadowRAM %08x, Data %02x ", (unsigned) a20addr, *data_ptr));
- break;
- default:
- BX_PANIC(("readPhysicalPage: default case"));
- } // Switch
- }
- }
- else {
- *data_ptr = vector[a20addr];
- BX_INFO(("Reading from Norm %08x, Data %02x ", (unsigned) a20addr, *data_ptr));
- }
- }
- else
- *data_ptr = 0xff;
-#endif // BX_PCI_SUPPORT == 0
- addr++;
- a20addr = (addr);
-#ifdef BX_LITTLE_ENDIAN
- data_ptr++;
-#else // BX_BIG_ENDIAN
- data_ptr--;
-#endif
- }
- return;
- }
-}
-
-#endif // #if BX_PROVIDE_CPU_MEMORY
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: memory.h,v 1.16 2003/08/05 13:19:35 cbothamy Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2001 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-
-#define BX_USE_MEM_SMF 0
-
-#if BX_USE_MEM_SMF
-// if static member functions on, then there is only one memory
-# define BX_MEM_SMF static
-# define BX_MEM_THIS BX_MEM(0)->
-#else
-# define BX_MEM_SMF
-# define BX_MEM_THIS this->
-#endif
-
-#if defined(__i386__)
-typedef Bit32u dma_addr_t;
-#elif defined(__x86_64__)
-typedef Bit64u dma_addr_t;
-#endif
-
-// alignment of memory vector, must be a power of 2
-#define BX_MEM_VECTOR_ALIGN 4096
-
-class BOCHSAPI BX_MEM_C : public logfunctions {
-
-public:
- Bit8u *actual_vector;
- Bit8u *vector; // aligned correctly
- size_t len;
- size_t dma_limit;
- size_t megabytes; // (len in Megabytes)
-#if BX_PCI_SUPPORT
- Bit8u shadow[4*16*4096]; // 256k of memory
-#endif
-#if BX_DEBUGGER
- unsigned char dbg_dirty_pages[(BX_MAX_DIRTY_PAGE_TABLE_MEGS * 1024 * 1024) / 4096];
- Bit32u dbg_count_dirty_pages () {
- return (BX_MAX_DIRTY_PAGE_TABLE_MEGS * 1024 * 1024) / 4096;
- }
-#endif
- unsigned long *page_array; /* for get_pfn_list() */
-
- BX_MEM_C(void);
- //BX_MEM_C(size_t memsize);
- ~BX_MEM_C(void);
- BX_MEM_SMF void alloc_vector_aligned (size_t bytes, size_t alignment) BX_CPP_AttrRegparmN(2);
- BX_MEM_SMF void init_memory(int memsize);
- BX_MEM_SMF void readPhysicalPage(BX_CPU_C *cpu, dma_addr_t addr,
- unsigned len, void *data) BX_CPP_AttrRegparmN(3);
- BX_MEM_SMF void writePhysicalPage(BX_CPU_C *cpu, dma_addr_t addr,
- unsigned len, void *data) BX_CPP_AttrRegparmN(3);
- BX_MEM_SMF void load_ROM(const char *path, Bit32u romaddress, Bit8u type);
- BX_MEM_SMF Bit32u get_memory_in_k(void);
-#if BX_PCI_SUPPORT
- BX_MEM_SMF Bit8u* pci_fetch_ptr(Bit32u addr) BX_CPP_AttrRegparmN(1);
-#endif
- BX_MEM_SMF bx_bool dbg_fetch_mem(Bit32u addr, unsigned len, Bit8u *buf);
- BX_MEM_SMF bx_bool dbg_set_mem(Bit32u addr, unsigned len, Bit8u *buf);
- BX_MEM_SMF bx_bool dbg_crc32(
- unsigned long (*f)(unsigned char *buf, int len),
- Bit32u addr1, Bit32u addr2, Bit32u *crc);
- BX_MEM_SMF Bit8u * getHostMemAddr(BX_CPU_C *cpu, Bit32u a20Addr, unsigned op) BX_CPP_AttrRegparmN(3);
- };
-
-#if BX_PROVIDE_CPU_MEMORY==1
-
-#if BX_SMP_PROCESSORS==1
-BOCHSAPI extern BX_MEM_C bx_mem;
-#else
-BOCHSAPI extern BX_MEM_C *bx_mem_array[BX_ADDRESS_SPACES];
-#endif /* BX_SMP_PROCESSORS */
-
-#endif /* BX_PROVIDE_CPU_MEMORY==1 */
-
-#if BX_DEBUGGER
-# define BX_DBG_DIRTY_PAGE(page) BX_MEM(0)->dbg_dirty_pages[page] = 1;
-#else
-# define BX_DBG_DIRTY_PAGE(page)
-#endif
+++ /dev/null
-/////////////////////////////////////////////////////////////////////////
-// $Id: misc_mem.cc,v 1.41 2003/09/10 16:34:56 vruppert Exp $
-/////////////////////////////////////////////////////////////////////////
-//
-// Copyright (C) 2002 MandrakeSoft S.A.
-//
-// MandrakeSoft S.A.
-// 43, rue d'Aboukir
-// 75002 Paris - France
-// http://www.linux-mandrake.com/
-// http://www.mandrakesoft.com/
-//
-// This library is free software; you can redistribute it and/or
-// modify it under the terms of the GNU Lesser General Public
-// License as published by the Free Software Foundation; either
-// version 2 of the License, or (at your option) any later version.
-//
-// This library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-// Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public
-// License along with this library; if not, write to the Free Software
-// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-
-
-
-
-
-
-#include "bochs.h"
-#ifdef BX_USE_VMX
-extern "C" {
-#include <sys/mman.h>
-}
-#endif
-
-#define LOG_THIS BX_MEM(0)->
-
-#if BX_PROVIDE_CPU_MEMORY
- Bit32u
-BX_MEM_C::get_memory_in_k(void)
-{
- return(BX_MEM_THIS megabytes * 1024);
-}
-#endif // #if BX_PROVIDE_CPU_MEMORY
-
-
-#if BX_PROVIDE_CPU_MEMORY
- // BX_MEM_C constructor
-BX_MEM_C::BX_MEM_C(void)
-{
- char mem[6];
- snprintf(mem, 6, "MEM%d", BX_SIM_ID);
- put(mem);
- settype(MEMLOG);
-
- vector = NULL;
- actual_vector = NULL;
- len = 0;
- megabytes = 0;
-}
-#endif // #if BX_PROVIDE_CPU_MEMORY
-
-
-
-#if BX_PROVIDE_CPU_MEMORY
-void BX_CPP_AttrRegparmN(2)
-BX_MEM_C::alloc_vector_aligned (size_t bytes, size_t alignment)
-{
- if (actual_vector != NULL) {
- BX_INFO (("freeing existing memory vector"));
- delete [] actual_vector;
- actual_vector = NULL;
- vector = NULL;
- }
- Bit64u test_mask = alignment - 1;
- actual_vector = new Bit8u [bytes+test_mask];
- // round address forward to nearest multiple of alignment. Alignment
- // MUST BE a power of two for this to work.
- unsigned long masked = ((unsigned long)(actual_vector + test_mask)) & ~test_mask;
- vector = (Bit8u *)masked;
- // sanity check: no lost bits during pointer conversion
- BX_ASSERT (sizeof(masked) >= sizeof(vector));
- // sanity check: after realignment, everything fits in allocated space
- BX_ASSERT (vector+bytes <= actual_vector+bytes+test_mask);
- BX_INFO (("allocated memory at %p. after alignment, vector=%p",
- actual_vector, vector));
-}
-#endif
-
-// We can't use this because alloc_vector_aligned uses BX_INFO, but the object does not yet exists
-/*
-#if BX_PROVIDE_CPU_MEMORY
- // BX_MEM_C constructor
-
-BX_MEM_C::BX_MEM_C(size_t memsize)
-{
- char mem[6];
- snprintf(mem, 6, "MEM%d", BX_SIM_ID);
- put(mem);
- settype(MEMLOG);
-
- vector = NULL;
- actual_vector = NULL;
- alloc_vector_aligned (memsize, BX_MEM_VECTOR_ALIGN);
- len = memsize;
- megabytes = len / (1024*1024);
-}
-#endif // #if BX_PROVIDE_CPU_MEMORY
-*/
-
-
-#if BX_PROVIDE_CPU_MEMORY
-// BX_MEM_C destructor
-BX_MEM_C::~BX_MEM_C(void)
-{
- if (this-> vector != NULL) {
- delete [] actual_vector;
- actual_vector = NULL;
- vector = NULL;
- }
- else {
- BX_DEBUG(("(%u) memory not freed as it wasn't allocated!", BX_SIM_ID));
- }
-}
-#endif // #if BX_PROVIDE_CPU_MEMORY
-
-
-#if BX_PROVIDE_CPU_MEMORY
- void
-BX_MEM_C::init_memory(int memsize)
-{
- BX_DEBUG(("Init $Id: misc_mem.cc,v 1.41 2003/09/10 16:34:56 vruppert Exp $"));
- // you can pass 0 if memory has been allocated already through
- // the constructor, or the desired size of memory if it hasn't
- // BX_INFO(("%.2fMB", (float)(BX_MEM_THIS megabytes) ));
-
-#ifndef BX_USE_VMX
- if (BX_MEM_THIS vector == NULL) {
- // memory not already allocated, do now...
- alloc_vector_aligned (memsize, BX_MEM_VECTOR_ALIGN);
-#endif
- BX_MEM_THIS len = memsize;
- BX_MEM_THIS megabytes = memsize / (1024*1024);
- BX_INFO(("%.2fMB", (float)(BX_MEM_THIS megabytes) ));
-#ifndef BX_USE_VMX
- }
-#endif
-
-#if BX_DEBUGGER
- if (megabytes > BX_MAX_DIRTY_PAGE_TABLE_MEGS) {
- BX_INFO(("Error: memory larger than dirty page table can handle"));
- BX_PANIC(("Error: increase BX_MAX_DIRTY_PAGE_TABLE_MEGS"));
- }
-#endif
-
- unsigned long nr_pages = megabytes * (1024 * 1024/getpagesize());
-
- if ( (page_array = (unsigned long *)
- malloc(nr_pages * sizeof(unsigned long))) == NULL)
- {
- BX_ERROR(("Could not allocate memory"));
- return;
- }
-
- if ( xc_get_pfn_list(xc_handle, domid, page_array, nr_pages) != nr_pages )
- {
- BX_ERROR(("Could not get the page frame list"));
- return;
- }
-
-#define PAGE_SHIFT 12
-#define PAGE_SIZE (1 << PAGE_SHIFT)
-
- if ((vector = (Bit8u *) xc_map_foreign_batch(xc_handle, domid,
- PROT_READ|PROT_WRITE,
- page_array,
- nr_pages - 1)) == 0) {
- BX_ERROR(("Could not map guest physical"));
- return;
- }
-
- BX_MEM_THIS dma_limit = (nr_pages - 1) << PAGE_SHIFT;
- BX_INFO(("DMA limit: %lx", BX_MEM_THIS dma_limit));
-
- shared_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
- PROT_READ|PROT_WRITE,
- page_array[nr_pages - 1]);
-}
-#endif // #if BX_PROVIDE_CPU_MEMORY
-
-
-#if BX_PROVIDE_CPU_MEMORY
- void
- // Values for type :
- // 0 : System Bios
- // 1 : VGA Bios
- // 2 : Optional ROM Bios
-BX_MEM_C::load_ROM(const char *path, Bit32u romaddress, Bit8u type)
-{
- struct stat stat_buf;
- int fd, ret;
- unsigned long size, offset;
-
- if (*path == '\0') {
- if (type == 2) {
- BX_PANIC(( "ROM: Optional BIOS image undefined."));
- }
- else if (type == 1) {
- BX_PANIC(( "ROM: VGA BIOS image undefined."));
- }
- else {
- BX_PANIC(( "ROM: System BIOS image undefined."));
- }
- return;
- }
- // read in ROM BIOS image file
- fd = open(path, O_RDONLY
-#ifdef O_BINARY
- | O_BINARY
-#endif
- );
- if (fd < 0) {
- if (type < 2) {
- BX_PANIC(( "ROM: couldn't open ROM image file '%s'.", path));
- }
- else {
- BX_ERROR(( "ROM: couldn't open ROM image file '%s'.", path));
- }
- return;
- }
- ret = fstat(fd, &stat_buf);
- if (ret) {
- if (type < 2) {
- BX_PANIC(( "ROM: couldn't stat ROM image file '%s'.", path));
- }
- else {
- BX_ERROR(( "ROM: couldn't stat ROM image file '%s'.", path));
- }
- return;
- }
-
- size = stat_buf.st_size;
-
- if ( (romaddress + size) > BX_MEM_THIS len ) {
- BX_PANIC(( "ROM: ROM address range > physical memsize!"));
- return;
- }
-
- offset = 0;
- while (size > 0) {
- ret = read(fd, (bx_ptr_t) &BX_MEM_THIS vector[romaddress + offset], size);
- if (ret <= 0) {
- BX_PANIC(( "ROM: read failed on BIOS image: '%s'",path));
- }
- size -= ret;
- offset += ret;
- }
- close(fd);
- BX_INFO(("rom at 0x%05x/%u ('%s')",
- (unsigned) romaddress,
- (unsigned) stat_buf.st_size,
- path
- ));
-}
-#endif // #if BX_PROVIDE_CPU_MEMORY
-
-#if BX_PCI_SUPPORT
- Bit8u* BX_CPP_AttrRegparmN(1)
-BX_MEM_C::pci_fetch_ptr(Bit32u addr)
-{
- if (bx_options.Oi440FXSupport->get ()) {
- switch (DEV_pci_rd_memtype (addr)) {
- case 0x1: // Read from ShadowRAM
- return (&BX_MEM_THIS shadow[addr - 0xc0000]);
-
- case 0x0: // Read from ROM
- return (&BX_MEM_THIS vector[addr]);
- default:
- BX_PANIC(("pci_fetch_ptr(): default case"));
- return(0);
- }
- }
- else
- return (&BX_MEM_THIS vector[addr]);
-}
-#endif
-
-
-#if ( BX_DEBUGGER || BX_DISASM || BX_GDBSTUB)
- bx_bool
-BX_MEM_C::dbg_fetch_mem(Bit32u addr, unsigned len, Bit8u *buf)
-{
- if ( (addr + len) > this->len ) {
- BX_INFO(("dbg_fetch_mem out of range. 0x%x > 0x%x",
- addr+len, this->len));
- return(0); // error, beyond limits of memory
- }
- for (; len>0; len--) {
- if ( (addr & 0xfffe0000) == 0x000a0000 ) {
- *buf = DEV_vga_mem_read(addr);
- }
- else {
-#if BX_PCI_SUPPORT == 0
- *buf = vector[addr];
-#else
- if ( bx_options.Oi440FXSupport->get () &&
- ((addr >= 0x000C0000) && (addr <= 0x000FFFFF)) ) {
- switch (DEV_pci_rd_memtype (addr)) {
- case 0x1: // Fetch from ShadowRAM
- *buf = shadow[addr - 0xc0000];
-// BX_INFO(("Fetching from ShadowRAM %06x, len %u !", (unsigned)addr, (unsigned)len));
- break;
-
- case 0x0: // Fetch from ROM
- *buf = vector[addr];
-// BX_INFO(("Fetching from ROM %06x, Data %02x ", (unsigned)addr, *buf));
- break;
- default:
- BX_PANIC(("dbg_fetch_mem: default case"));
- }
- }
- else
- *buf = vector[addr];
-#endif // #if BX_PCI_SUPPORT == 0
- }
- buf++;
- addr++;
- }
- return(1);
-}
-#endif
-
-#if BX_DEBUGGER || BX_GDBSTUB
- bx_bool
-BX_MEM_C::dbg_set_mem(Bit32u addr, unsigned len, Bit8u *buf)
-{
- if ( (addr + len) > this->len ) {
- return(0); // error, beyond limits of memory
- }
- for (; len>0; len--) {
- if ( (addr & 0xfffe0000) == 0x000a0000 ) {
- DEV_vga_mem_write(addr, *buf);
- }
- else
- vector[addr] = *buf;
- buf++;
- addr++;
- }
- return(1);
-}
-#endif
-
- bx_bool
-BX_MEM_C::dbg_crc32(unsigned long (*f)(unsigned char *buf, int len),
- Bit32u addr1, Bit32u addr2, Bit32u *crc)
-{
- unsigned len;
-
- *crc = 0;
- if (addr1 > addr2)
- return(0);
-
- if (addr2 >= this->len) {
- return(0); // error, specified address past last phy mem addr
- }
-
- len = 1 + addr2 - addr1;
- *crc = f(vector + addr1, len);
-
- return(1);
-}
-
-
- Bit8u * BX_CPP_AttrRegparmN(3)
-BX_MEM_C::getHostMemAddr(BX_CPU_C *cpu, Bit32u a20Addr, unsigned op)
- // Return a host address corresponding to the guest physical memory
- // address (with A20 already applied), given that the calling
- // code will perform an 'op' operation. This address will be
- // used for direct access to guest memory as an acceleration by
- // a few instructions, like REP {MOV, INS, OUTS, etc}.
- // Values of 'op' are { BX_READ, BX_WRITE, BX_RW }.
-
- // The other assumption is that the calling code _only_ accesses memory
- // directly within the page that encompasses the address requested.
-{
- if ( a20Addr >= BX_MEM_THIS len )
- return(NULL); // Error, requested addr is out of bounds.
- if (op == BX_READ) {
- if ( (a20Addr > 0x9ffff) && (a20Addr < 0xc0000) )
- return(NULL); // Vetoed! Mem mapped IO (VGA)
-#if !BX_PCI_SUPPORT
- return( (Bit8u *) & vector[a20Addr] );
-#else
- else if ( (a20Addr < 0xa0000) || (a20Addr > 0xfffff)
- || (!bx_options.Oi440FXSupport->get ()) )
- return( (Bit8u *) & vector[a20Addr] );
- else {
- switch (DEV_pci_rd_memtype (a20Addr)) {
- case 0x0: // Read from ROM
- return ( (Bit8u *) & vector[a20Addr]);
- case 0x1: // Read from ShadowRAM
- return( (Bit8u *) & shadow[a20Addr - 0xc0000]);
- default:
- BX_PANIC(("getHostMemAddr(): default case"));
- return(0);
- }
- }
-#endif
- }
- else { // op == {BX_WRITE, BX_RW}
- Bit8u *retAddr;
-
- if ( (a20Addr < 0xa0000) || (a20Addr > 0xfffff) ) {
- retAddr = (Bit8u *) & vector[a20Addr];
- }
-#if !BX_PCI_SUPPORT
- else
- return(NULL); // Vetoed! Mem mapped IO (VGA) and ROMs
-#else
- else if ( (a20Addr < 0xc0000) || (!bx_options.Oi440FXSupport->get ()) )
- return(NULL); // Vetoed! Mem mapped IO (VGA) and ROMs
- else if (DEV_pci_wr_memtype (a20Addr) == 1) {
- // Write to ShadowRAM
- retAddr = (Bit8u *) & shadow[a20Addr - 0xc0000];
- }
- else
- return(NULL); // Vetoed! ROMs
-#endif
-
-#if BX_SupportICache
- cpu->iCache.decWriteStamp(cpu, a20Addr);
-#endif
-
- return(retAddr);
- }
-}
+++ /dev/null
-CXXFLAGS += -O2 -I../../../tools/libxc -I../../../xen/include/public
-clean:
- $(RM) -f *.o *~ lib*.a device-model
-
-install::
-
--- /dev/null
+/*
+ * QEMU monitor
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+#include <dirent.h>
+
+//#define DEBUG
+//#define DEBUG_COMPLETION
+
+#ifndef offsetof
+#define offsetof(type, field) ((size_t) &((type *)0)->field)
+#endif
+
+/*
+ * Supported types:
+ *
+ * 'F' filename
+ * 'B' block device name
+ * 's' string (accept optional quote)
+ * 'i' integer
+ * '/' optional gdb-like print format (like "/10x")
+ *
+ * '?' optional type (for 'F', 's' and 'i')
+ *
+ */
+
+typedef struct term_cmd_t {
+ const char *name;
+ const char *args_type;
+ void (*handler)();
+ const char *params;
+ const char *help;
+} term_cmd_t;
+
+static CharDriverState *monitor_hd;
+
+static term_cmd_t term_cmds[];
+static term_cmd_t info_cmds[];
+
+static char term_outbuf[1024];
+static int term_outbuf_index;
+
+static void monitor_start_input(void);
+
+void term_flush(void)
+{
+ if (term_outbuf_index > 0) {
+ if(monitor_hd)
+ qemu_chr_write(monitor_hd, term_outbuf, term_outbuf_index);
+ else
+ fwrite(term_outbuf, term_outbuf_index, 1, stderr);
+ term_outbuf_index = 0;
+ }
+}
+
+/* flush at every end of line or if the buffer is full */
+void term_puts(const char *str)
+{
+ int c;
+ for(;;) {
+ c = *str++;
+ if (c == '\0')
+ break;
+ term_outbuf[term_outbuf_index++] = c;
+ if (term_outbuf_index >= sizeof(term_outbuf) ||
+ c == '\n')
+ term_flush();
+ }
+}
+
+void term_vprintf(const char *fmt, va_list ap)
+{
+ char buf[4096];
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ term_puts(buf);
+}
+
+void term_printf(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ term_vprintf(fmt, ap);
+ va_end(ap);
+}
+
+static int compare_cmd(const char *name, const char *list)
+{
+ const char *p, *pstart;
+ int len;
+ len = strlen(name);
+ p = list;
+ for(;;) {
+ pstart = p;
+ p = strchr(p, '|');
+ if (!p)
+ p = pstart + strlen(pstart);
+ if ((p - pstart) == len && !memcmp(pstart, name, len))
+ return 1;
+ if (*p == '\0')
+ break;
+ p++;
+ }
+ return 0;
+}
+
+static void do_quit(void)
+{
+ extern int domid;
+ extern FILE* logfile;
+ char destroy_cmd[20];
+ sprintf(destroy_cmd, "xm destroy %d", domid);
+ if (system(destroy_cmd) == -1)
+ fprintf(logfile, "%s failed.!\n", destroy_cmd);
+ exit(0);
+}
+
+static term_cmd_t term_cmds[] = {
+ { "q|quit", "", do_quit,
+ "", "quit the emulator" },
+ { NULL, NULL, },
+};
+
+#define MAX_ARGS 16
+
+static void monitor_handle_command(const char *cmdline)
+{
+ const char *p, *pstart, *typestr;
+ char *q;
+ int c, nb_args, len, i;
+ term_cmd_t *cmd;
+ char cmdname[256];
+ void *str_allocated[MAX_ARGS];
+ void *args[MAX_ARGS];
+
+#ifdef DEBUG
+ term_printf("command='%s'\n", cmdline);
+#endif
+
+ /* extract the command name */
+ p = cmdline;
+ q = cmdname;
+ while (isspace(*p))
+ p++;
+ if (*p == '\0')
+ return;
+ pstart = p;
+ while (*p != '\0' && *p != '/' && !isspace(*p))
+ p++;
+ len = p - pstart;
+ if (len > sizeof(cmdname) - 1)
+ len = sizeof(cmdname) - 1;
+ memcpy(cmdname, pstart, len);
+ cmdname[len] = '\0';
+
+ /* find the command */
+ for(cmd = term_cmds; cmd->name != NULL; cmd++) {
+ if (compare_cmd(cmdname, cmd->name))
+ goto found;
+ }
+ term_printf("unknown command: '%s'\n", cmdname);
+ return;
+ found:
+
+ for(i = 0; i < MAX_ARGS; i++)
+ str_allocated[i] = NULL;
+
+ /* parse the parameters */
+ typestr = cmd->args_type;
+ nb_args = 0;
+ for(;;) {
+ c = *typestr;
+ if (c == '\0')
+ break;
+ typestr++;
+ switch(c) {
+ /* TODO: add more commands we need here to support vmx device model */
+ case 'F':
+ case 'B':
+ case 's':
+ case '/':
+ case 'i':
+ case '-':
+ default:
+ term_printf("%s: unknown type '%c', we only support quit command now.\n", cmdname, c);
+ goto fail;
+ }
+ }
+ /* check that all arguments were parsed */
+ while (isspace(*p))
+ p++;
+ if (*p != '\0') {
+ term_printf("%s: extraneous characters at the end of line\n",
+ cmdname);
+ goto fail;
+ }
+
+ switch(nb_args) {
+ case 0:
+ cmd->handler();
+ break;
+ case 1:
+ cmd->handler(args[0]);
+ break;
+ case 2:
+ cmd->handler(args[0], args[1]);
+ break;
+ case 3:
+ cmd->handler(args[0], args[1], args[2]);
+ break;
+ case 4:
+ cmd->handler(args[0], args[1], args[2], args[3]);
+ break;
+ case 5:
+ cmd->handler(args[0], args[1], args[2], args[3], args[4]);
+ break;
+ case 6:
+ cmd->handler(args[0], args[1], args[2], args[3], args[4], args[5]);
+ break;
+ default:
+ term_printf("unsupported number of arguments: %d\n", nb_args);
+ goto fail;
+ }
+ fail:
+ for(i = 0; i < MAX_ARGS; i++)
+ qemu_free(str_allocated[i]);
+ return;
+}
+
+static int term_can_read(void *opaque)
+{
+ return 128;
+}
+
+static void term_read(void *opaque, const uint8_t *buf, int size)
+{
+ int i;
+ for(i = 0; i < size; i++)
+ readline_handle_byte(buf[i]);
+}
+
+static void monitor_start_input(void);
+
+static void monitor_handle_command1(void *opaque, const char *cmdline)
+{
+ monitor_handle_command(cmdline);
+ monitor_start_input();
+}
+
+static void monitor_start_input(void)
+{
+ readline_start("(VTXen) ", 0, monitor_handle_command1, NULL);
+}
+
+void monitor_init(CharDriverState *hd, int show_banner)
+{
+ monitor_hd = hd;
+ if (show_banner) {
+ term_printf("VMX device model. type 'q' to exit\n");
+ }
+ qemu_chr_add_read_handler(hd, term_can_read, term_read, NULL);
+ monitor_start_input();
+}
--- /dev/null
+/*
+ * QEMU low level functions
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include "cpu.h"
+
+#if defined(__i386__) && !defined(CONFIG_SOFTMMU) && !defined(CONFIG_USER_ONLY)
+
+#include <sys/mman.h>
+#include <sys/ipc.h>
+
+/* When not using soft mmu, libc independant functions are needed for
+ the CPU core because it needs to use alternates stacks and
+ libc/thread incompatibles settings */
+
+#include <linux/unistd.h>
+
+#define QEMU_SYSCALL0(name) \
+{ \
+long __res; \
+__asm__ volatile ("int $0x80" \
+ : "=a" (__res) \
+ : "0" (__NR_##name)); \
+return __res; \
+}
+
+#define QEMU_SYSCALL1(name,arg1) \
+{ \
+long __res; \
+__asm__ volatile ("int $0x80" \
+ : "=a" (__res) \
+ : "0" (__NR_##name),"b" ((long)(arg1))); \
+return __res; \
+}
+
+#define QEMU_SYSCALL2(name,arg1,arg2) \
+{ \
+long __res; \
+__asm__ volatile ("int $0x80" \
+ : "=a" (__res) \
+ : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2))); \
+return __res; \
+}
+
+#define QEMU_SYSCALL3(name,arg1,arg2,arg3) \
+{ \
+long __res; \
+__asm__ volatile ("int $0x80" \
+ : "=a" (__res) \
+ : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
+ "d" ((long)(arg3))); \
+return __res; \
+}
+
+#define QEMU_SYSCALL4(name,arg1,arg2,arg3,arg4) \
+{ \
+long __res; \
+__asm__ volatile ("int $0x80" \
+ : "=a" (__res) \
+ : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
+ "d" ((long)(arg3)),"S" ((long)(arg4))); \
+return __res; \
+}
+
+#define QEMU_SYSCALL5(name,arg1,arg2,arg3,arg4,arg5) \
+{ \
+long __res; \
+__asm__ volatile ("int $0x80" \
+ : "=a" (__res) \
+ : "0" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
+ "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5))); \
+return __res; \
+}
+
+#define QEMU_SYSCALL6(name,arg1,arg2,arg3,arg4,arg5,arg6) \
+{ \
+long __res; \
+__asm__ volatile ("push %%ebp ; movl %%eax,%%ebp ; movl %1,%%eax ; int $0x80 ; pop %%ebp" \
+ : "=a" (__res) \
+ : "i" (__NR_##name),"b" ((long)(arg1)),"c" ((long)(arg2)), \
+ "d" ((long)(arg3)),"S" ((long)(arg4)),"D" ((long)(arg5)), \
+ "0" ((long)(arg6))); \
+return __res; \
+}
+
+int qemu_write(int fd, const void *buf, size_t n)
+{
+ QEMU_SYSCALL3(write, fd, buf, n);
+}
+
+
+
+/****************************************************************/
+/* shmat replacement */
+
+int qemu_ipc(int call, unsigned long first,
+ unsigned long second, unsigned long third,
+ void *ptr, unsigned long fifth)
+{
+ QEMU_SYSCALL6(ipc, call, first, second, third, ptr, fifth);
+}
+
+#define SHMAT 21
+
+/* we must define shmat so that a specific address will be used when
+ mapping the X11 ximage */
+void *shmat(int shmid, const void *shmaddr, int shmflg)
+{
+ void *ptr;
+ int ret;
+ /* we give an address in the right memory area */
+ if (!shmaddr)
+ shmaddr = get_mmap_addr(8192 * 1024);
+ ret = qemu_ipc(SHMAT, shmid, shmflg, (unsigned long)&ptr, (void *)shmaddr, 0);
+ if (ret < 0)
+ return NULL;
+ return ptr;
+}
+
+/****************************************************************/
+/* sigaction bypassing the threads */
+
+static int kernel_sigaction(int signum, const struct qemu_sigaction *act,
+ struct qemu_sigaction *oldact,
+ int sigsetsize)
+{
+ QEMU_SYSCALL4(rt_sigaction, signum, act, oldact, sigsetsize);
+}
+
+int qemu_sigaction(int signum, const struct qemu_sigaction *act,
+ struct qemu_sigaction *oldact)
+{
+ return kernel_sigaction(signum, act, oldact, 8);
+}
+
+/****************************************************************/
+/* memory allocation */
+
+//#define DEBUG_MALLOC
+
+#define MALLOC_BASE 0xab000000
+#define PHYS_RAM_BASE 0xac000000
+
+#define MALLOC_ALIGN 16
+#define BLOCK_HEADER_SIZE 16
+
+typedef struct MemoryBlock {
+ struct MemoryBlock *next;
+ unsigned long size; /* size of block, including header */
+} MemoryBlock;
+
+static MemoryBlock *first_free_block;
+static unsigned long malloc_addr = MALLOC_BASE;
+
+static void *malloc_get_space(size_t size)
+{
+ void *ptr;
+ size = TARGET_PAGE_ALIGN(size);
+ ptr = mmap((void *)malloc_addr, size,
+ PROT_WRITE | PROT_READ,
+ MAP_PRIVATE | MAP_FIXED | MAP_ANON, -1, 0);
+ if (ptr == MAP_FAILED)
+ return NULL;
+ malloc_addr += size;
+ return ptr;
+}
+
+void *qemu_malloc(size_t size)
+{
+ MemoryBlock *mb, *mb1, **pmb;
+ void *ptr;
+ size_t size1, area_size;
+
+ if (size == 0)
+ return NULL;
+
+ size = (size + BLOCK_HEADER_SIZE + MALLOC_ALIGN - 1) & ~(MALLOC_ALIGN - 1);
+ pmb = &first_free_block;
+ for(;;) {
+ mb = *pmb;
+ if (mb == NULL)
+ break;
+ if (size <= mb->size)
+ goto found;
+ pmb = &mb->next;
+ }
+ /* no big enough blocks found: get new space */
+ area_size = TARGET_PAGE_ALIGN(size);
+ mb = malloc_get_space(area_size);
+ if (!mb)
+ return NULL;
+ size1 = area_size - size;
+ if (size1 > 0) {
+ /* create a new free block */
+ mb1 = (MemoryBlock *)((uint8_t *)mb + size);
+ mb1->next = NULL;
+ mb1->size = size1;
+ *pmb = mb1;
+ }
+ goto the_end;
+ found:
+ /* a free block was found: use it */
+ size1 = mb->size - size;
+ if (size1 > 0) {
+ /* create a new free block */
+ mb1 = (MemoryBlock *)((uint8_t *)mb + size);
+ mb1->next = mb->next;
+ mb1->size = size1;
+ *pmb = mb1;
+ } else {
+ /* suppress the first block */
+ *pmb = mb->next;
+ }
+ the_end:
+ mb->size = size;
+ mb->next = NULL;
+ ptr = ((uint8_t *)mb + BLOCK_HEADER_SIZE);
+#ifdef DEBUG_MALLOC
+ qemu_printf("malloc: size=0x%x ptr=0x%lx\n", size, (unsigned long)ptr);
+#endif
+ return ptr;
+}
+
+void qemu_free(void *ptr)
+{
+ MemoryBlock *mb;
+
+ if (!ptr)
+ return;
+ mb = (MemoryBlock *)((uint8_t *)ptr - BLOCK_HEADER_SIZE);
+ mb->next = first_free_block;
+ first_free_block = mb;
+}
+
+/****************************************************************/
+/* virtual memory allocation */
+
+unsigned long mmap_addr = PHYS_RAM_BASE;
+
+void *get_mmap_addr(unsigned long size)
+{
+ unsigned long addr;
+ addr = mmap_addr;
+ mmap_addr += ((size + 4095) & ~4095) + 4096;
+ return (void *)addr;
+}
+
+#else
+
+int qemu_write(int fd, const void *buf, size_t n)
+{
+ int ret;
+ ret = write(fd, buf, n);
+ if (ret < 0)
+ return -errno;
+ else
+ return ret;
+}
+
+void *get_mmap_addr(unsigned long size)
+{
+ return NULL;
+}
+
+void qemu_free(void *ptr)
+{
+ free(ptr);
+}
+
+void *qemu_malloc(size_t size)
+{
+ return malloc(size);
+}
+
+#endif
+
+void *qemu_mallocz(size_t size)
+{
+ void *ptr;
+ ptr = qemu_malloc(size);
+ if (!ptr)
+ return NULL;
+ memset(ptr, 0, size);
+ return ptr;
+}
+
+char *qemu_strdup(const char *str)
+{
+ char *ptr;
+ ptr = qemu_malloc(strlen(str) + 1);
+ if (!ptr)
+ return NULL;
+ strcpy(ptr, str);
+ return ptr;
+}
+
+/****************************************************************/
+/* printf support */
+
+static inline int qemu_isdigit(int c)
+{
+ return c >= '0' && c <= '9';
+}
+
+#define OUTCHAR(c) (buflen > 0? (--buflen, *buf++ = (c)): 0)
+
+/* from BSD ppp sources */
+int qemu_vsnprintf(char *buf, int buflen, const char *fmt, va_list args)
+{
+ int c, i, n;
+ int width, prec, fillch;
+ int base, len, neg;
+ unsigned long val = 0;
+ const char *f;
+ char *str, *buf0;
+ char num[32];
+ static const char hexchars[] = "0123456789abcdef";
+
+ buf0 = buf;
+ --buflen;
+ while (buflen > 0) {
+ for (f = fmt; *f != '%' && *f != 0; ++f)
+ ;
+ if (f > fmt) {
+ len = f - fmt;
+ if (len > buflen)
+ len = buflen;
+ memcpy(buf, fmt, len);
+ buf += len;
+ buflen -= len;
+ fmt = f;
+ }
+ if (*fmt == 0)
+ break;
+ c = *++fmt;
+ width = prec = 0;
+ fillch = ' ';
+ if (c == '0') {
+ fillch = '0';
+ c = *++fmt;
+ }
+ if (c == '*') {
+ width = va_arg(args, int);
+ c = *++fmt;
+ } else {
+ while (qemu_isdigit(c)) {
+ width = width * 10 + c - '0';
+ c = *++fmt;
+ }
+ }
+ if (c == '.') {
+ c = *++fmt;
+ if (c == '*') {
+ prec = va_arg(args, int);
+ c = *++fmt;
+ } else {
+ while (qemu_isdigit(c)) {
+ prec = prec * 10 + c - '0';
+ c = *++fmt;
+ }
+ }
+ }
+ /* modifiers */
+ switch(c) {
+ case 'l':
+ c = *++fmt;
+ break;
+ default:
+ break;
+ }
+ str = 0;
+ base = 0;
+ neg = 0;
+ ++fmt;
+ switch (c) {
+ case 'd':
+ i = va_arg(args, int);
+ if (i < 0) {
+ neg = 1;
+ val = -i;
+ } else
+ val = i;
+ base = 10;
+ break;
+ case 'o':
+ val = va_arg(args, unsigned int);
+ base = 8;
+ break;
+ case 'x':
+ case 'X':
+ val = va_arg(args, unsigned int);
+ base = 16;
+ break;
+ case 'p':
+ val = (unsigned long) va_arg(args, void *);
+ base = 16;
+ neg = 2;
+ break;
+ case 's':
+ str = va_arg(args, char *);
+ break;
+ case 'c':
+ num[0] = va_arg(args, int);
+ num[1] = 0;
+ str = num;
+ break;
+ default:
+ *buf++ = '%';
+ if (c != '%')
+ --fmt; /* so %z outputs %z etc. */
+ --buflen;
+ continue;
+ }
+ if (base != 0) {
+ str = num + sizeof(num);
+ *--str = 0;
+ while (str > num + neg) {
+ *--str = hexchars[val % base];
+ val = val / base;
+ if (--prec <= 0 && val == 0)
+ break;
+ }
+ switch (neg) {
+ case 1:
+ *--str = '-';
+ break;
+ case 2:
+ *--str = 'x';
+ *--str = '0';
+ break;
+ }
+ len = num + sizeof(num) - 1 - str;
+ } else {
+ len = strlen(str);
+ if (prec > 0 && len > prec)
+ len = prec;
+ }
+ if (width > 0) {
+ if (width > buflen)
+ width = buflen;
+ if ((n = width - len) > 0) {
+ buflen -= n;
+ for (; n > 0; --n)
+ *buf++ = fillch;
+ }
+ }
+ if (len > buflen)
+ len = buflen;
+ memcpy(buf, str, len);
+ buf += len;
+ buflen -= len;
+ }
+ *buf = 0;
+ return buf - buf0;
+}
+
+void qemu_vprintf(const char *fmt, va_list ap)
+{
+ char buf[1024];
+ int len;
+
+ len = qemu_vsnprintf(buf, sizeof(buf), fmt, ap);
+ qemu_write(1, buf, len);
+}
+
+void qemu_printf(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ qemu_vprintf(fmt, ap);
+ va_end(ap);
+}
+
--- /dev/null
+#ifndef QEMU_OSDEP_H
+#define QEMU_OSDEP_H
+
+#include <stdarg.h>
+
+int qemu_vsnprintf(char *buf, int buflen, const char *fmt, va_list args);
+void qemu_vprintf(const char *fmt, va_list ap);
+void qemu_printf(const char *fmt, ...);
+
+void *qemu_malloc(size_t size);
+void *qemu_mallocz(size_t size);
+void qemu_free(void *ptr);
+char *qemu_strdup(const char *str);
+
+void *get_mmap_addr(unsigned long size);
+
+/* specific kludges for OS compatibility (should be moved elsewhere) */
+#if defined(__i386__) && !defined(CONFIG_SOFTMMU) && !defined(CONFIG_USER_ONLY)
+
+/* disabled pthread version of longjmp which prevent us from using an
+ alternative signal stack */
+extern void __longjmp(jmp_buf env, int val);
+#define longjmp __longjmp
+
+#include <signal.h>
+
+/* NOTE: it works only because the glibc sigset_t is >= kernel sigset_t */
+struct qemu_sigaction {
+ union {
+ void (*_sa_handler)(int);
+ void (*_sa_sigaction)(int, struct siginfo *, void *);
+ } _u;
+ unsigned long sa_flags;
+ void (*sa_restorer)(void);
+ sigset_t sa_mask; /* mask last for extensibility */
+};
+
+int qemu_sigaction(int signum, const struct qemu_sigaction *act,
+ struct qemu_sigaction *oldact);
+
+#undef sigaction
+#undef sa_handler
+#undef sa_sigaction
+#define sigaction qemu_sigaction
+#define sa_handler _u._sa_handler
+#define sa_sigaction _u._sa_sigaction
+
+#endif
+
+#endif
--- /dev/null
+/* Code to mangle pathnames into those matching a given prefix.
+ eg. open("/lib/foo.so") => open("/usr/gnemul/i386-linux/lib/foo.so");
+
+ The assumption is that this area does not change.
+*/
+#include <sys/types.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdio.h>
+#include "qemu.h"
+
+struct pathelem
+{
+ /* Name of this, eg. lib */
+ char *name;
+ /* Full path name, eg. /usr/gnemul/x86-linux/lib. */
+ char *pathname;
+ struct pathelem *parent;
+ /* Children */
+ unsigned int num_entries;
+ struct pathelem *entries[0];
+};
+
+static struct pathelem *base;
+
+/* First N chars of S1 match S2, and S2 is N chars long. */
+static int strneq(const char *s1, unsigned int n, const char *s2)
+{
+ unsigned int i;
+
+ for (i = 0; i < n; i++)
+ if (s1[i] != s2[i])
+ return 0;
+ return s2[i] == 0;
+}
+
+static struct pathelem *add_entry(struct pathelem *root, const char *name);
+
+static struct pathelem *new_entry(const char *root,
+ struct pathelem *parent,
+ const char *name)
+{
+ struct pathelem *new = malloc(sizeof(*new));
+ new->name = strdup(name);
+ asprintf(&new->pathname, "%s/%s", root, name);
+ new->num_entries = 0;
+ return new;
+}
+
+#define streq(a,b) (strcmp((a), (b)) == 0)
+
+static struct pathelem *add_dir_maybe(struct pathelem *path)
+{
+ DIR *dir;
+
+ if ((dir = opendir(path->pathname)) != NULL) {
+ struct dirent *dirent;
+
+ while ((dirent = readdir(dir)) != NULL) {
+ if (!streq(dirent->d_name,".") && !streq(dirent->d_name,"..")){
+ path = add_entry(path, dirent->d_name);
+ }
+ }
+ closedir(dir);
+ }
+ return path;
+}
+
+static struct pathelem *add_entry(struct pathelem *root, const char *name)
+{
+ root->num_entries++;
+
+ root = realloc(root, sizeof(*root)
+ + sizeof(root->entries[0])*root->num_entries);
+
+ root->entries[root->num_entries-1] = new_entry(root->pathname, root, name);
+ root->entries[root->num_entries-1]
+ = add_dir_maybe(root->entries[root->num_entries-1]);
+ return root;
+}
+
+/* This needs to be done after tree is stabalized (ie. no more reallocs!). */
+static void set_parents(struct pathelem *child, struct pathelem *parent)
+{
+ unsigned int i;
+
+ child->parent = parent;
+ for (i = 0; i < child->num_entries; i++)
+ set_parents(child->entries[i], child);
+}
+
+void init_paths(const char *prefix)
+{
+ if (prefix[0] != '/' ||
+ prefix[0] == '\0' ||
+ !strcmp(prefix, "/"))
+ return;
+
+ base = new_entry("", NULL, prefix+1);
+ base = add_dir_maybe(base);
+ if (base->num_entries == 0) {
+ free (base);
+ base = NULL;
+ } else {
+ set_parents(base, base);
+ }
+}
+
+/* FIXME: Doesn't handle DIR/.. where DIR is not in emulated dir. */
+static const char *
+follow_path(const struct pathelem *cursor, const char *name)
+{
+ unsigned int i, namelen;
+
+ name += strspn(name, "/");
+ namelen = strcspn(name, "/");
+
+ if (namelen == 0)
+ return cursor->pathname;
+
+ if (strneq(name, namelen, ".."))
+ return follow_path(cursor->parent, name + namelen);
+
+ if (strneq(name, namelen, "."))
+ return follow_path(cursor, name + namelen);
+
+ for (i = 0; i < cursor->num_entries; i++)
+ if (strneq(name, namelen, cursor->entries[i]->name))
+ return follow_path(cursor->entries[i], name + namelen);
+
+ /* Not found */
+ return NULL;
+}
+
+/* Look for path in emulation dir, otherwise return name. */
+const char *path(const char *name)
+{
+ /* Only do absolute paths: quick and dirty, but should mostly be OK.
+ Could do relative by tracking cwd. */
+ if (!base || name[0] != '/')
+ return name;
+
+ return follow_path(base, name) ?: name;
+}
--- /dev/null
+#
+# NOTE: only compilable with x86 cross compile tools
+#
+include ../config-host.mak
+
+DEFINES=
+
+TARGETS=
+ifeq ($(ARCH),i386)
+TARGETS+=linux_boot.bin
+endif
+
+all: $(TARGETS)
+
+linux_boot.bin: linux_boot.o
+ ld --oformat binary -Ttext 0 -o $@ $<
+ chmod a-x $@
+
+%.o: %.S
+ $(CC) $(DEFINES) -c -o $@ $<
+
+clean:
+ rm -f $(TARGETS) *.o *~
+
--- /dev/null
+- The PC BIOS comes from the Bochs project
+ (http://bochs.sourceforge.net/). A patch from bios.diff was applied.
+
+- The VGA BIOS and the Cirrus VGA BIOS come from the LGPL VGA bios
+ project (http://www.nongnu.org/vgabios/).
+
+- The PowerPC Open Hack'Ware Open Firmware Compatible BIOS is
+ available at http://site.voila.fr/jmayer/OpenHackWare/index.htm.
+
+- Proll is a GPL'd boot PROM for Sparc JavaStations
+ (http://people.redhat.com/zaitcev/linux/).
+ Applying proll.patch allows circumventing some bugs and enables
+ faster kernel load through a hack.
--- /dev/null
+Index: rombios.c
+===================================================================
+RCS file: /cvsroot/bochs/bochs/bios/rombios.c,v
+retrieving revision 1.110
+diff -u -w -r1.110 rombios.c
+--- rombios.c 31 May 2004 13:11:27 -0000 1.110
++++ rombios.c 7 Oct 2004 21:23:50 -0000
+@@ -137,6 +137,7 @@
+ #define DEBUG_INT16 0
+ #define DEBUG_INT1A 0
+ #define DEBUG_INT74 0
++#define DEBUG_APM 0
+
+ #define BX_CPU 3
+ #define BX_USE_PS2_MOUSE 1
+@@ -145,6 +146,7 @@
+ #define BX_SUPPORT_FLOPPY 1
+ #define BX_FLOPPY_ON_CNT 37 // 2 seconds
+ #define BX_PCIBIOS 1
++#define BX_APM 1
+
+ #define BX_USE_ATADRV 1
+ #define BX_ELTORITO_BOOT 1
+@@ -230,17 +232,6 @@
+ out dx,ax
+ MEND
+
+-MACRO HALT2
+- ;; the HALT macro is called with the line number of the HALT call.
+- ;; The line number is then sent to the PANIC_PORT, causing Bochs/Plex
+- ;; to print a BX_PANIC message. This will normally halt the simulation
+- ;; with a message such as "BIOS panic at rombios.c, line 4091".
+- ;; However, users can choose to make panics non-fatal and continue.
+- mov dx,#PANIC_PORT2
+- mov ax,#?1
+- out dx,ax
+-MEND
+-
+ MACRO JMP_AP
+ db 0xea
+ dw ?2
+@@ -1543,15 +1534,12 @@
+ }
+
+ if (action & BIOS_PRINTF_HALT) {
+- // freeze in a busy loop. If I do a HLT instruction, then in versions
+- // 1.3.pre1 and earlier, it will panic without ever updating the VGA
+- // display, so the panic message will not be visible. By waiting
+- // forever, you are certain to see the panic message on screen.
+- // After a few more versions have passed, we can turn this back into
+- // a halt or something.
+- // do {} while (1);
++ // freeze in a busy loop.
+ ASM_START
+- HALT2(__LINE__)
++ cli
++ halt2_loop:
++ hlt
++ jmp halt2_loop
+ ASM_END
+ }
+ }
+@@ -5412,8 +5400,8 @@
+ case 0x03: SET_BL( 0x06 ); break;
+ }
+
+- DI = 0xefc7;
+- ES = 0xf000;
++ DI = read_word(0x00, 0x1e*4); // INT vector 0x1E
++ ES = read_word(0x00, 0x1e*4+2);
+ goto int13_success;
+ break;
+
+@@ -6984,8 +6972,8 @@
+ }
+
+ /* set es & di to point to 11 byte diskette param table in ROM */
+- DI = 0xefc7;
+- ES = 0xf000;
++ DI = read_word(0x00, 0x1e*4); // INT vector 0x1E
++ ES = read_word(0x00, 0x1e*4+2);
+ CLEAR_CF(); // success
+ /* disk status not changed upon success */
+ return;
+@@ -7880,7 +7868,7 @@
+ mov al, #0x02
+ out #0x0a, al ;; clear DMA-1 channel 2 mask bit
+
+- SET_INT_VECTOR(0x1E, #0xF000, #diskette_param_table)
++ SET_INT_VECTOR(0x1E, #0xF000, #diskette_param_table2)
+ SET_INT_VECTOR(0x40, #0xF000, #int13_diskette)
+ SET_INT_VECTOR(0x0E, #0xF000, #int0e_handler) ;; IRQ 6
+
+@@ -8344,6 +8332,19 @@
+ pop ax
+ iret
+
++
++;--------------------
++#if BX_APM
++use32 386
++#define APM_PROT32
++#include "apmbios.S"
++use16 386
++
++#define APM_REAL
++#include "apmbios.S"
++
++#endif
++
+ ;--------------------
+ #if BX_PCIBIOS
+ use32 386
+@@ -9515,6 +9516,26 @@
+ pop ds
+ iret
+
++diskette_param_table2:
++;; New diskette parameter table adding 3 parameters from IBM
++;; Since no provisions are made for multiple drive types, most
++;; values in this table are ignored. I set parameters for 1.44M
++;; floppy here
++db 0xAF
++db 0x02 ;; head load time 0000001, DMA used
++db 0x25
++db 0x02
++db 18
++db 0x1B
++db 0xFF
++db 0x6C
++db 0xF6
++db 0x0F
++db 0x08
++db 79 ;; maximum track
++db 0 ;; data transfer rate
++db 4 ;; drive type in cmos
++
+ .org 0xf045 ; INT 10 Functions 0-Fh Entry Point
+ HALT(__LINE__)
+ iret
+@@ -9560,6 +9581,10 @@
+ .org 0xf859 ; INT 15h System Services Entry Point
+ int15_handler:
+ pushf
++#if BX_APM
++ cmp ah, #0x53
++ je apm_call
++#endif
+ push ds
+ push es
+ pushad
+@@ -9570,6 +9595,10 @@
+ popf
+ //JMPL(iret_modify_cf)
+ jmp iret_modify_cf
++#if BX_APM
++apm_call:
++ jmp _apmreal_entry
++#endif
+
+ ;; Protected mode IDT descriptor
+ ;;
--- /dev/null
+/*
+ * QEMU Boot sector to launch a preloaded Linux kernel
+ * Copyright (c) 2004 Fabrice Bellard
+ */
+
+#define LOAD_SEG 0x9000
+
+.code16
+.text
+ .globl _start
+
+_start:
+ cli
+ cld
+ mov $LOAD_SEG, %ax
+ mov %ax, %ds
+ mov %ax, %es
+ mov %ax, %fs
+ mov %ax, %gs
+ mov %ax, %ss
+ mov $0x8ffe, %sp
+ ljmp $LOAD_SEG + 0x20, $0
+
+1:
+ .fill 510 - (1b - _start), 1, 0
+
+ /* boot sector signature */
+ .byte 0x55
+ .byte 0xaa
--- /dev/null
+diff -ru proll_18.orig/mrcoffee/main.c proll_18/mrcoffee/main.c
+--- proll_18.orig/mrcoffee/main.c 2002-09-13 16:16:59.000000000 +0200
++++ proll_18/mrcoffee/main.c 2004-09-26 11:52:23.000000000 +0200
+@@ -101,6 +101,7 @@
+ le_probe();
+ init_net();
+
++#ifdef ORIG
+ #if 0 /* RARP */
+ if (rarp() != 0) fatal();
+ /* printrarp(); */
+@@ -117,13 +118,20 @@
+ xtoa(myipaddr, fname, 8);
+ if (load(boot_rec.bp_siaddr, fname) != 0) fatal();
+ #endif
++#endif
+
+ romvec = init_openprom(bb.nbanks, bb.bankv, hiphybas);
+
+ printk("Memory used: virt 0x%x:0x%x[%dK] iomap 0x%x:0x%x\n",
+ PROLBASE, (int)cmem.curp, ((unsigned) cmem.curp - PROLBASE)/1024,
+ (int)cio.start, (int)cio.curp);
++#ifdef ORIG
+ set_timeout(5); while (!chk_timeout()) { } /* P3: let me read */
++#else
++ printk("loading kernel:");
++ i = ld_bypass(0x20000000);
++ printk(" done, size %d\n", i);
++#endif
+
+ {
+ void (*entry)(void *, int) = (void (*)(void*, int)) LOADBASE;
+diff -ru proll_18.orig/mrcoffee/openprom.c proll_18/mrcoffee/openprom.c
+--- proll_18.orig/mrcoffee/openprom.c 2002-09-13 16:17:03.000000000 +0200
++++ proll_18/mrcoffee/openprom.c 2004-09-21 21:27:16.000000000 +0200
+@@ -144,10 +144,14 @@
+ };
+
+ static int cpu_nctx = NCTX_SWIFT;
++static int cpu_cache_line_size = 0x20;
++static int cpu_cache_nlines = 0x200;
+ static struct property propv_cpu[] = {
+ {"name", "STP1012PGA", sizeof("STP1012PGA") },
+ {"device_type", "cpu", 4 },
+ {"mmu-nctx", (char*)&cpu_nctx, sizeof(int)},
++ {"cache-line-size", (char*)&cpu_cache_line_size, sizeof(int)},
++ {"cache-nlines", (char*)&cpu_cache_nlines, sizeof(int)},
+ {NULL, NULL, -1}
+ };
+
--- /dev/null
+#!/bin/sh
+# enable automatic i386/ARM/SPARC/PPC program execution by the kernel
+
+# load the binfmt_misc module
+/sbin/modprobe binfmt_misc
+
+# probe cpu type
+cpu=`uname -m`
+case "$cpu" in
+ i386|i486|i586|i686|i86pc|BePC)
+ cpu="i386"
+ ;;
+ "Power Macintosh"|ppc|ppc64)
+ cpu="ppc"
+ ;;
+ armv4l)
+ cpu="arm"
+ ;;
+esac
+
+# register the interpreter for each cpu except for the native one
+if [ $cpu != "i386" ] ; then
+ echo ':i386:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03\x00:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfb\xff\xff\xff:/usr/local/bin/qemu-i386:' > /proc/sys/fs/binfmt_misc/register
+ echo ':i486:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x06\x00:\xff\xff\xff\xff\xff\xfe\xfe\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfb\xff\xff\xff:/usr/local/bin/qemu-i386:' > /proc/sys/fs/binfmt_misc/register
+fi
+if [ $cpu != "arm" ] ; then
+ echo ':arm:M::\x7fELF\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x28\x00:\xff\xff\xff\xff\xff\xff\xff\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfb\xff\xff\xff:/usr/local/bin/qemu-arm:' > /proc/sys/fs/binfmt_misc/register
+fi
+if [ $cpu != "sparc" ] ; then
+ echo ':sparc:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x02:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfb\xff\xff\xff:/usr/local/bin/qemu-sparc:' > /proc/sys/fs/binfmt_misc/register
+fi
+if [ $cpu != "ppc" ] ; then
+ echo ':ppc:M::\x7fELF\x01\x02\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x14:\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xff\xfb\xff\xff\xff:/usr/local/bin/qemu-ppc:' > /proc/sys/fs/binfmt_misc/register
+fi
--- /dev/null
+<HTML>
+<HEAD>
+<!-- Created by texi2html 1.56k from qemu-doc.texi on 19 May 2005 -->
+
+<TITLE>QEMU CPU Emulator User Documentation</TITLE>
+</HEAD>
+<BODY>
+<H1>QEMU CPU Emulator User Documentation</H1>
+<P>
+<P><HR><P>
+<H1>Table of Contents</H1>
+<UL>
+<LI><A NAME="TOC1" HREF="qemu-doc.html#SEC1">1. Introduction</A>
+<UL>
+<LI><A NAME="TOC2" HREF="qemu-doc.html#SEC2">1.1 Features</A>
+</UL>
+<LI><A NAME="TOC3" HREF="qemu-doc.html#SEC3">2. Installation</A>
+<UL>
+<LI><A NAME="TOC4" HREF="qemu-doc.html#SEC4">2.1 Linux</A>
+<LI><A NAME="TOC5" HREF="qemu-doc.html#SEC5">2.2 Windows</A>
+<LI><A NAME="TOC6" HREF="qemu-doc.html#SEC6">2.3 Mac OS X</A>
+</UL>
+<LI><A NAME="TOC7" HREF="qemu-doc.html#SEC7">3. QEMU PC System emulator invocation</A>
+<UL>
+<LI><A NAME="TOC8" HREF="qemu-doc.html#SEC8">3.1 Introduction</A>
+<LI><A NAME="TOC9" HREF="qemu-doc.html#SEC9">3.2 Quick Start</A>
+<LI><A NAME="TOC10" HREF="qemu-doc.html#SEC10">3.3 Invocation</A>
+<LI><A NAME="TOC11" HREF="qemu-doc.html#SEC11">3.4 Keys</A>
+<LI><A NAME="TOC12" HREF="qemu-doc.html#SEC12">3.5 QEMU Monitor</A>
+<UL>
+<LI><A NAME="TOC13" HREF="qemu-doc.html#SEC13">3.5.1 Commands</A>
+<LI><A NAME="TOC14" HREF="qemu-doc.html#SEC14">3.5.2 Integer expressions</A>
+</UL>
+<LI><A NAME="TOC15" HREF="qemu-doc.html#SEC15">3.6 Disk Images</A>
+<UL>
+<LI><A NAME="TOC16" HREF="qemu-doc.html#SEC16">3.6.1 Raw disk images</A>
+<LI><A NAME="TOC17" HREF="qemu-doc.html#SEC17">3.6.2 Snapshot mode</A>
+<LI><A NAME="TOC18" HREF="qemu-doc.html#SEC18">3.6.3 Copy On Write disk images</A>
+<LI><A NAME="TOC19" HREF="qemu-doc.html#SEC19">3.6.4 Convert VMware disk images to raw disk images</A>
+</UL>
+<LI><A NAME="TOC20" HREF="qemu-doc.html#SEC20">3.7 Network emulation</A>
+<UL>
+<LI><A NAME="TOC21" HREF="qemu-doc.html#SEC21">3.7.1 Using tun/tap network interface</A>
+<LI><A NAME="TOC22" HREF="qemu-doc.html#SEC22">3.7.2 Using the user mode network stack</A>
+</UL>
+<LI><A NAME="TOC23" HREF="qemu-doc.html#SEC23">3.8 Direct Linux Boot</A>
+<LI><A NAME="TOC24" HREF="qemu-doc.html#SEC24">3.9 Linux Kernel Compilation</A>
+<LI><A NAME="TOC25" HREF="qemu-doc.html#SEC25">3.10 GDB usage</A>
+<LI><A NAME="TOC26" HREF="qemu-doc.html#SEC26">3.11 Target OS specific information</A>
+<UL>
+<LI><A NAME="TOC27" HREF="qemu-doc.html#SEC27">3.11.1 Linux</A>
+<LI><A NAME="TOC28" HREF="qemu-doc.html#SEC28">3.11.2 Windows</A>
+<UL>
+<LI><A NAME="TOC29" HREF="qemu-doc.html#SEC29">3.11.2.1 SVGA graphic modes support</A>
+<LI><A NAME="TOC30" HREF="qemu-doc.html#SEC30">3.11.2.2 CPU usage reduction</A>
+<LI><A NAME="TOC31" HREF="qemu-doc.html#SEC31">3.11.2.3 Windows 2000 disk full problems</A>
+<LI><A NAME="TOC32" HREF="qemu-doc.html#SEC32">3.11.2.4 Windows XP security problems</A>
+</UL>
+<LI><A NAME="TOC33" HREF="qemu-doc.html#SEC33">3.11.3 MS-DOS and FreeDOS</A>
+<UL>
+<LI><A NAME="TOC34" HREF="qemu-doc.html#SEC34">3.11.3.1 CPU usage reduction</A>
+</UL>
+</UL>
+</UL>
+<LI><A NAME="TOC35" HREF="qemu-doc.html#SEC35">4. QEMU PowerPC System emulator invocation</A>
+<LI><A NAME="TOC36" HREF="qemu-doc.html#SEC36">5. QEMU User space emulator invocation</A>
+<UL>
+<LI><A NAME="TOC37" HREF="qemu-doc.html#SEC37">5.1 Quick Start</A>
+<LI><A NAME="TOC38" HREF="qemu-doc.html#SEC38">5.2 Wine launch</A>
+<LI><A NAME="TOC39" HREF="qemu-doc.html#SEC39">5.3 Command line options</A>
+</UL>
+<LI><A NAME="TOC40" HREF="qemu-doc.html#SEC40">6. Compilation from the sources</A>
+<UL>
+<LI><A NAME="TOC41" HREF="qemu-doc.html#SEC41">6.1 Linux/BSD</A>
+<LI><A NAME="TOC42" HREF="qemu-doc.html#SEC42">6.2 Windows</A>
+<LI><A NAME="TOC43" HREF="qemu-doc.html#SEC43">6.3 Cross compilation for Windows with Linux</A>
+<LI><A NAME="TOC44" HREF="qemu-doc.html#SEC44">6.4 Mac OS X</A>
+</UL>
+</UL>
+<P><HR><P>
+
+<P>
+QEMU CPU Emulator User Documentation
+
+
+
+
+<H1><A NAME="SEC1" HREF="qemu-doc.html#TOC1">1. Introduction</A></H1>
+
+
+
+<H2><A NAME="SEC2" HREF="qemu-doc.html#TOC2">1.1 Features</A></H2>
+
+<P>
+QEMU is a FAST! processor emulator using dynamic translation to
+achieve good emulation speed.
+
+
+<P>
+QEMU has two operating modes:
+
+
+
+<UL>
+
+<LI>
+
+Full system emulation. In this mode, QEMU emulates a full system (for
+example a PC), including a processor and various peripherials. It can
+be used to launch different Operating Systems without rebooting the
+PC or to debug system code.
+
+<LI>
+
+User mode emulation (Linux host only). In this mode, QEMU can launch
+Linux processes compiled for one CPU on another CPU. It can be used to
+launch the Wine Windows API emulator (<A HREF="http://www.winehq.org">http://www.winehq.org</A>) or
+to ease cross-compilation and cross-debugging.
+
+</UL>
+
+<P>
+As QEMU requires no host kernel driver to run, it is very safe and
+easy to use.
+
+
+<P>
+For system emulation, the following hardware targets are supported:
+
+<UL>
+<LI>PC (x86 processor)
+
+<LI>PREP (PowerPC processor)
+
+<LI>PowerMac (PowerPC processor, in progress)
+
+</UL>
+
+<P>
+For user emulation, x86, PowerPC, ARM, and SPARC CPUs are supported.
+
+
+
+
+<H1><A NAME="SEC3" HREF="qemu-doc.html#TOC3">2. Installation</A></H1>
+
+<P>
+If you want to compile QEMU yourself, see section <A HREF="qemu-doc.html#SEC40">6. Compilation from the sources</A>.
+
+
+
+
+<H2><A NAME="SEC4" HREF="qemu-doc.html#TOC4">2.1 Linux</A></H2>
+
+<P>
+Download the binary distribution (<TT>`qemu-XXX-i386.tar.gz'</TT>) and
+untar it as root in <TT>`/'</TT>:
+
+
+
+<PRE>
+su
+cd /
+tar zxvf /tmp/qemu-XXX-i386.tar.gz
+</PRE>
+
+
+
+<H2><A NAME="SEC5" HREF="qemu-doc.html#TOC5">2.2 Windows</A></H2>
+
+<P>
+Download the experimental binary installer at
+<A HREF="http://www.freeoszoo.org/download.php">http://www.freeoszoo.org/download.php</A>.
+
+
+
+
+<H2><A NAME="SEC6" HREF="qemu-doc.html#TOC6">2.3 Mac OS X</A></H2>
+
+<P>
+Download the experimental binary installer at
+<A HREF="http://www.freeoszoo.org/download.php">http://www.freeoszoo.org/download.php</A>.
+
+
+
+
+<H1><A NAME="SEC7" HREF="qemu-doc.html#TOC7">3. QEMU PC System emulator invocation</A></H1>
+
+
+
+<H2><A NAME="SEC8" HREF="qemu-doc.html#TOC8">3.1 Introduction</A></H2>
+
+<P>
+The QEMU System emulator simulates a complete PC.
+
+
+<P>
+In order to meet specific user needs, two versions of QEMU are
+available:
+
+
+
+<OL>
+
+<LI>
+
+<CODE>qemu-fast</CODE> uses the host Memory Management Unit (MMU) to
+simulate the x86 MMU. It is <EM>fast</EM> but has limitations because
+the whole 4 GB address space cannot be used and some memory mapped
+peripherials cannot be emulated accurately yet. Therefore, a specific
+guest Linux kernel can be used (See section <A HREF="qemu-doc.html#SEC24">3.9 Linux Kernel Compilation</A>) as guest
+OS.
+
+Moreover there is no separation between the host and target address
+spaces, so it offers no security (the target OS can modify the
+<CODE>qemu-fast</CODE> code by writing at the right addresses).
+
+<LI>
+
+<CODE>qemu</CODE> uses a software MMU. It is about <EM>two times slower</EM>
+but gives a more accurate emulation and a complete separation between
+the host and target address spaces.
+
+</OL>
+
+<P>
+QEMU emulates the following PC peripherials:
+
+
+
+<UL>
+<LI>
+
+i440FX host PCI bridge and PIIX3 PCI to ISA bridge
+<LI>
+
+Cirrus CLGD 5446 PCI VGA card or dummy VGA card with Bochs VESA
+extensions (hardware level, including all non standard modes).
+<LI>
+
+PS/2 mouse and keyboard
+<LI>
+
+2 PCI IDE interfaces with hard disk and CD-ROM support
+<LI>
+
+Floppy disk
+<LI>
+
+NE2000 PCI network adapters
+<LI>
+
+Serial ports
+<LI>
+
+Soundblaster 16 card
+</UL>
+
+<P>
+QEMU uses the PC BIOS from the Bochs project and the Plex86/Bochs LGPL
+VGA BIOS.
+
+
+
+
+<H2><A NAME="SEC9" HREF="qemu-doc.html#TOC9">3.2 Quick Start</A></H2>
+
+<P>
+Download and uncompress the linux image (<TT>`linux.img'</TT>) and type:
+
+
+
+<PRE>
+qemu linux.img
+</PRE>
+
+<P>
+Linux should boot and give you a prompt.
+
+
+
+
+<H2><A NAME="SEC10" HREF="qemu-doc.html#TOC10">3.3 Invocation</A></H2>
+
+
+<PRE>
+usage: qemu [options] [disk_image]
+</PRE>
+
+<P>
+<VAR>disk_image</VAR> is a raw hard disk image for IDE hard disk 0.
+
+
+<P>
+General options:
+<DL COMPACT>
+
+<DT>@option{-fda file}
+<DD>
+<DT>@option{-fdb file}
+<DD>
+Use <VAR>file</VAR> as floppy disk 0/1 image (See section <A HREF="qemu-doc.html#SEC15">3.6 Disk Images</A>). You can
+use the host floppy by using <TT>`/dev/fd0'</TT> as filename.
+
+<DT>@option{-hda file}
+<DD>
+<DT>@option{-hdb file}
+<DD>
+<DT>@option{-hdc file}
+<DD>
+<DT>@option{-hdd file}
+<DD>
+Use <VAR>file</VAR> as hard disk 0, 1, 2 or 3 image (See section <A HREF="qemu-doc.html#SEC15">3.6 Disk Images</A>).
+
+<DT>@option{-cdrom file}
+<DD>
+Use <VAR>file</VAR> as CD-ROM image (you cannot use @option{-hdc} and and
+@option{-cdrom} at the same time). You can use the host CD-ROM by
+using <TT>`/dev/cdrom'</TT> as filename.
+
+<DT>@option{-boot [a|c|d]}
+<DD>
+Boot on floppy (a), hard disk (c) or CD-ROM (d). Hard disk boot is
+the default.
+
+<DT>@option{-snapshot}
+<DD>
+Write to temporary files instead of disk image files. In this case,
+the raw disk image you use is not written back. You can however force
+the write back by pressing <KBD>C-a s</KBD> (See section <A HREF="qemu-doc.html#SEC15">3.6 Disk Images</A>).
+
+<DT>@option{-m megs}
+<DD>
+Set virtual RAM size to <VAR>megs</VAR> megabytes. Default is 128 MB.
+
+<DT>@option{-nographic}
+<DD>
+Normally, QEMU uses SDL to display the VGA output. With this option,
+you can totally disable graphical output so that QEMU is a simple
+command line application. The emulated serial port is redirected on
+the console. Therefore, you can still use QEMU to debug a Linux kernel
+with a serial console.
+
+<DT>@option{-enable-audio}
+<DD>
+The SB16 emulation is disabled by default as it may give problems with
+Windows. You can enable it manually with this option.
+
+<DT>@option{-localtime}
+<DD>
+Set the real time clock to local time (the default is to UTC
+time). This option is needed to have correct date in MS-DOS or
+Windows.
+
+<DT>@option{-full-screen}
+<DD>
+Start in full screen.
+
+</DL>
+
+<P>
+Network options:
+
+
+<DL COMPACT>
+
+<DT>@option{-n script}
+<DD>
+Set TUN/TAP network init script [default=/etc/qemu-ifup]. This script
+is launched to configure the host network interface (usually tun0)
+corresponding to the virtual NE2000 card.
+
+<DT>@option{-macaddr addr}
+<DD>
+Set the mac address of the first interface (the format is
+aa:bb:cc:dd:ee:ff in hexa). The mac address is incremented for each
+new network interface.
+
+<DT>@option{-tun-fd fd}
+<DD>
+Assumes <VAR>fd</VAR> talks to a tap/tun host network interface and use
+it. Read <A HREF="http://bellard.org/qemu/tetrinet.html">http://bellard.org/qemu/tetrinet.html</A> to have an
+example of its use.
+
+<DT>@option{-user-net}
+<DD>
+Use the user mode network stack. This is the default if no tun/tap
+network init script is found.
+
+<DT>@option{-tftp prefix}
+<DD>
+When using the user mode network stack, activate a built-in TFTP
+server. All filenames beginning with <VAR>prefix</VAR> can be downloaded
+from the host to the guest using a TFTP client. The TFTP client on the
+guest must be configured in binary mode (use the command <CODE>bin</CODE> of
+the Unix TFTP client). The host IP address on the guest is as usual
+10.0.2.2.
+
+<DT>@option{-smb dir}
+<DD>
+When using the user mode network stack, activate a built-in SMB
+server so that Windows OSes can access to the host files in <TT>`dir'</TT>
+transparently.
+
+In the guest Windows OS, the line:
+
+<PRE>
+10.0.2.4 smbserver
+</PRE>
+
+must be added in the file <TT>`C:\WINDOWS\LMHOSTS'</TT> (for windows 9x/Me)
+or <TT>`C:\WINNT\SYSTEM32\DRIVERS\ETC\LMHOSTS'</TT> (Windows NT/2000).
+
+Then <TT>`dir'</TT> can be accessed in <TT>`\\smbserver\qemu'</TT>.
+
+Note that a SAMBA server must be installed on the host OS in
+<TT>`/usr/sbin/smbd'</TT>. QEMU was tested succesfully with smbd version
+2.2.7a from the Red Hat 9.
+
+<DT>@option{-redir [tcp|udp]:host-port:[guest-host]:guest-port}
+<DD>
+When using the user mode network stack, redirect incoming TCP or UDP
+connections to the host port <VAR>host-port</VAR> to the guest
+<VAR>guest-host</VAR> on guest port <VAR>guest-port</VAR>. If <VAR>guest-host</VAR>
+is not specified, its value is 10.0.2.15 (default address given by the
+built-in DHCP server).
+
+For example, to redirect host X11 connection from screen 1 to guest
+screen 0, use the following:
+
+
+<PRE>
+# on the host
+qemu -redir tcp:6001::6000 [...]
+# this host xterm should open in the guest X11 server
+xterm -display :1
+</PRE>
+
+To redirect telnet connections from host port 5555 to telnet port on
+the guest, use the following:
+
+
+<PRE>
+# on the host
+qemu -redir tcp:5555::23 [...]
+telnet localhost 5555
+</PRE>
+
+Then when you use on the host <CODE>telnet localhost 5555</CODE>, you
+connect to the guest telnet server.
+
+<DT>@option{-dummy-net}
+<DD>
+Use the dummy network stack: no packet will be received by the network
+cards.
+
+</DL>
+
+<P>
+Linux boot specific. When using this options, you can use a given
+Linux kernel without installing it in the disk image. It can be useful
+for easier testing of various kernels.
+
+
+<DL COMPACT>
+
+<DT>@option{-kernel bzImage}
+<DD>
+Use <VAR>bzImage</VAR> as kernel image.
+
+<DT>@option{-append cmdline}
+<DD>
+Use <VAR>cmdline</VAR> as kernel command line
+
+<DT>@option{-initrd file}
+<DD>
+Use <VAR>file</VAR> as initial ram disk.
+
+</DL>
+
+<P>
+Debug/Expert options:
+<DL COMPACT>
+
+<DT>@option{-serial dev}
+<DD>
+Redirect the virtual serial port to host device <VAR>dev</VAR>. Available
+devices are:
+<DL COMPACT>
+
+<DT><CODE>vc</CODE>
+<DD>
+Virtual console
+<DT><CODE>pty</CODE>
+<DD>
+[Linux only] Pseudo TTY (a new PTY is automatically allocated)
+<DT><CODE>null</CODE>
+<DD>
+void device
+<DT><CODE>stdio</CODE>
+<DD>
+[Unix only] standard input/output
+</DL>
+The default device is <CODE>vc</CODE> in graphical mode and <CODE>stdio</CODE> in
+non graphical mode.
+
+This option can be used several times to simulate up to 4 serials
+ports.
+
+<DT>@option{-monitor dev}
+<DD>
+Redirect the monitor to host device <VAR>dev</VAR> (same devices as the
+serial port).
+The default device is <CODE>vc</CODE> in graphical mode and <CODE>stdio</CODE> in
+non graphical mode.
+
+<DT>@option{-s}
+<DD>
+Wait gdb connection to port 1234 (See section <A HREF="qemu-doc.html#SEC25">3.10 GDB usage</A>).
+<DT>@option{-p port}
+<DD>
+Change gdb connection port.
+<DT>@option{-S}
+<DD>
+Do not start CPU at startup (you must type 'c' in the monitor).
+<DT>@option{-d}
+<DD>
+Output log in /tmp/qemu.log
+<DT>@option{-isa}
+<DD>
+Simulate an ISA-only system (default is PCI system).
+<DT>@option{-std-vga}
+<DD>
+Simulate a standard VGA card with Bochs VBE extensions (default is
+Cirrus Logic GD5446 PCI VGA)
+<DT>@option{-loadvm file}
+<DD>
+Start right away with a saved state (<CODE>loadvm</CODE> in monitor)
+</DL>
+
+
+
+<H2><A NAME="SEC11" HREF="qemu-doc.html#TOC11">3.4 Keys</A></H2>
+
+<P>
+During the graphical emulation, you can use the following keys:
+<DL COMPACT>
+
+<DT><KBD>Ctrl-Alt-f</KBD>
+<DD>
+Toggle full screen
+
+<DT><KBD>Ctrl-Alt-n</KBD>
+<DD>
+Switch to virtual console 'n'. Standard console mappings are:
+<DL COMPACT>
+
+<DT><EM>1</EM>
+<DD>
+Target system display
+<DT><EM>2</EM>
+<DD>
+Monitor
+<DT><EM>3</EM>
+<DD>
+Serial port
+</DL>
+
+<DT><KBD>Ctrl-Alt</KBD>
+<DD>
+Toggle mouse and keyboard grab.
+</DL>
+
+<P>
+In the virtual consoles, you can use <KBD>Ctrl-Up</KBD>, <KBD>Ctrl-Down</KBD>,
+<KBD>Ctrl-PageUp</KBD> and <KBD>Ctrl-PageDown</KBD> to move in the back log.
+
+
+<P>
+During emulation, if you are using the @option{-nographic} option, use
+<KBD>Ctrl-a h</KBD> to get terminal commands:
+
+
+<DL COMPACT>
+
+<DT><KBD>Ctrl-a h</KBD>
+<DD>
+Print this help
+<DT><KBD>Ctrl-a x</KBD>
+<DD>
+Exit emulatior
+<DT><KBD>Ctrl-a s</KBD>
+<DD>
+Save disk data back to file (if -snapshot)
+<DT><KBD>Ctrl-a b</KBD>
+<DD>
+Send break (magic sysrq in Linux)
+<DT><KBD>Ctrl-a c</KBD>
+<DD>
+Switch between console and monitor
+<DT><KBD>Ctrl-a Ctrl-a</KBD>
+<DD>
+Send Ctrl-a
+</DL>
+
+
+
+<H2><A NAME="SEC12" HREF="qemu-doc.html#TOC12">3.5 QEMU Monitor</A></H2>
+
+<P>
+The QEMU monitor is used to give complex commands to the QEMU
+emulator. You can use it to:
+
+
+
+<UL>
+
+<LI>
+
+Remove or insert removable medias images
+(such as CD-ROM or floppies)
+
+<LI>
+
+Freeze/unfreeze the Virtual Machine (VM) and save or restore its state
+from a disk file.
+
+<LI>Inspect the VM state without an external debugger.
+
+</UL>
+
+
+
+<H3><A NAME="SEC13" HREF="qemu-doc.html#TOC13">3.5.1 Commands</A></H3>
+
+<P>
+The following commands are available:
+
+
+<DL COMPACT>
+
+<DT>@option{help or ? [cmd]}
+<DD>
+Show the help for all commands or just for command <VAR>cmd</VAR>.
+
+<DT>@option{commit}
+<DD>
+Commit changes to the disk images (if -snapshot is used)
+
+<DT>@option{info subcommand}
+<DD>
+show various information about the system state
+
+<DL COMPACT>
+
+<DT>@option{info network}
+<DD>
+show the network state
+<DT>@option{info block}
+<DD>
+show the block devices
+<DT>@option{info registers}
+<DD>
+show the cpu registers
+<DT>@option{info history}
+<DD>
+show the command line history
+</DL>
+
+<DT>@option{q or quit}
+<DD>
+Quit the emulator.
+
+<DT>@option{eject [-f] device}
+<DD>
+Eject a removable media (use -f to force it).
+
+<DT>@option{change device filename}
+<DD>
+Change a removable media.
+
+<DT>@option{screendump filename}
+<DD>
+Save screen into PPM image <VAR>filename</VAR>.
+
+<DT>@option{log item1[,...]}
+<DD>
+Activate logging of the specified items to <TT>`/tmp/qemu.log'</TT>.
+
+<DT>@option{savevm filename}
+<DD>
+Save the whole virtual machine state to <VAR>filename</VAR>.
+
+<DT>@option{loadvm filename}
+<DD>
+Restore the whole virtual machine state from <VAR>filename</VAR>.
+
+<DT>@option{stop}
+<DD>
+Stop emulation.
+
+<DT>@option{c or cont}
+<DD>
+Resume emulation.
+
+<DT>@option{gdbserver [port]}
+<DD>
+Start gdbserver session (default port=1234)
+
+<DT>@option{x/fmt addr}
+<DD>
+Virtual memory dump starting at <VAR>addr</VAR>.
+
+<DT>@option{xp /fmt addr}
+<DD>
+Physical memory dump starting at <VAR>addr</VAR>.
+
+<VAR>fmt</VAR> is a format which tells the command how to format the
+data. Its syntax is: @option{/{count}{format}{size}}
+
+<DL COMPACT>
+
+<DT><VAR>count</VAR>
+<DD>
+is the number of items to be dumped.
+
+<DT><VAR>format</VAR>
+<DD>
+can be x (hexa), d (signed decimal), u (unsigned decimal), o (octal),
+c (char) or i (asm instruction).
+
+<DT><VAR>size</VAR>
+<DD>
+can be b (8 bits), h (16 bits), w (32 bits) or g (64 bits). On x86,
+<CODE>h</CODE> or <CODE>w</CODE> can be specified with the <CODE>i</CODE> format to
+respectively select 16 or 32 bit code instruction size.
+
+</DL>
+
+Examples:
+
+<UL>
+<LI>
+
+Dump 10 instructions at the current instruction pointer:
+
+<PRE>
+(qemu) x/10i $eip
+0x90107063: ret
+0x90107064: sti
+0x90107065: lea 0x0(%esi,1),%esi
+0x90107069: lea 0x0(%edi,1),%edi
+0x90107070: ret
+0x90107071: jmp 0x90107080
+0x90107073: nop
+0x90107074: nop
+0x90107075: nop
+0x90107076: nop
+</PRE>
+
+<LI>
+
+Dump 80 16 bit values at the start of the video memory.
+
+<PRE>
+(qemu) xp/80hx 0xb8000
+0x000b8000: 0x0b50 0x0b6c 0x0b65 0x0b78 0x0b38 0x0b36 0x0b2f 0x0b42
+0x000b8010: 0x0b6f 0x0b63 0x0b68 0x0b73 0x0b20 0x0b56 0x0b47 0x0b41
+0x000b8020: 0x0b42 0x0b69 0x0b6f 0x0b73 0x0b20 0x0b63 0x0b75 0x0b72
+0x000b8030: 0x0b72 0x0b65 0x0b6e 0x0b74 0x0b2d 0x0b63 0x0b76 0x0b73
+0x000b8040: 0x0b20 0x0b30 0x0b35 0x0b20 0x0b4e 0x0b6f 0x0b76 0x0b20
+0x000b8050: 0x0b32 0x0b30 0x0b30 0x0b33 0x0720 0x0720 0x0720 0x0720
+0x000b8060: 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720
+0x000b8070: 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720
+0x000b8080: 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720
+0x000b8090: 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720
+</PRE>
+
+</UL>
+
+<DT>@option{p or print/fmt expr}
+<DD>
+Print expression value. Only the <VAR>format</VAR> part of <VAR>fmt</VAR> is
+used.
+
+<DT>@option{sendkey keys}
+<DD>
+Send <VAR>keys</VAR> to the emulator. Use <CODE>-</CODE> to press several keys
+simultaneously. Example:
+
+<PRE>
+sendkey ctrl-alt-f1
+</PRE>
+
+This command is useful to send keys that your graphical user interface
+intercepts at low level, such as <CODE>ctrl-alt-f1</CODE> in X Window.
+
+<DT>@option{system_reset}
+<DD>
+Reset the system.
+
+</DL>
+
+
+
+<H3><A NAME="SEC14" HREF="qemu-doc.html#TOC14">3.5.2 Integer expressions</A></H3>
+
+<P>
+The monitor understands integers expressions for every integer
+argument. You can use register names to get the value of specifics
+CPU registers by prefixing them with <EM>$</EM>.
+
+
+
+
+<H2><A NAME="SEC15" HREF="qemu-doc.html#TOC15">3.6 Disk Images</A></H2>
+
+
+
+<H3><A NAME="SEC16" HREF="qemu-doc.html#TOC16">3.6.1 Raw disk images</A></H3>
+
+<P>
+The disk images can simply be raw images of the hard disk. You can
+create them with the command:
+
+<PRE>
+dd of=myimage bs=1024 seek=mysize count=0
+</PRE>
+
+<P>
+where <VAR>myimage</VAR> is the image filename and <VAR>mysize</VAR> is its size
+in kilobytes.
+
+
+
+
+<H3><A NAME="SEC17" HREF="qemu-doc.html#TOC17">3.6.2 Snapshot mode</A></H3>
+
+<P>
+If you use the option @option{-snapshot}, all disk images are
+considered as read only. When sectors in written, they are written in
+a temporary file created in <TT>`/tmp'</TT>. You can however force the
+write back to the raw disk images by pressing <KBD>C-a s</KBD>.
+
+
+<P>
+NOTE: The snapshot mode only works with raw disk images.
+
+
+
+
+<H3><A NAME="SEC18" HREF="qemu-doc.html#TOC18">3.6.3 Copy On Write disk images</A></H3>
+
+<P>
+QEMU also supports user mode Linux
+(<A HREF="http://user-mode-linux.sourceforge.net/">http://user-mode-linux.sourceforge.net/</A>) Copy On Write (COW)
+disk images. The COW disk images are much smaller than normal images
+as they store only modified sectors. They also permit the use of the
+same disk image template for many users.
+
+
+<P>
+To create a COW disk images, use the command:
+
+
+
+<PRE>
+qemu-mkcow -f myrawimage.bin mycowimage.cow
+</PRE>
+
+<P>
+<TT>`myrawimage.bin'</TT> is a raw image you want to use as original disk
+image. It will never be written to.
+
+
+<P>
+<TT>`mycowimage.cow'</TT> is the COW disk image which is created by
+<CODE>qemu-mkcow</CODE>. You can use it directly with the @option{-hdx}
+options. You must not modify the original raw disk image if you use
+COW images, as COW images only store the modified sectors from the raw
+disk image. QEMU stores the original raw disk image name and its
+modified time in the COW disk image so that chances of mistakes are
+reduced.
+
+
+<P>
+If the raw disk image is not read-only, by pressing <KBD>C-a s</KBD> you
+can flush the COW disk image back into the raw disk image, as in
+snapshot mode.
+
+
+<P>
+COW disk images can also be created without a corresponding raw disk
+image. It is useful to have a big initial virtual disk image without
+using much disk space. Use:
+
+
+
+<PRE>
+qemu-mkcow mycowimage.cow 1024
+</PRE>
+
+<P>
+to create a 1 gigabyte empty COW disk image.
+
+
+<P>
+NOTES:
+
+<OL>
+<LI>
+
+COW disk images must be created on file systems supporting
+<EM>holes</EM> such as ext2 or ext3.
+<LI>
+
+Since holes are used, the displayed size of the COW disk image is not
+the real one. To know it, use the <CODE>ls -ls</CODE> command.
+</OL>
+
+
+
+<H3><A NAME="SEC19" HREF="qemu-doc.html#TOC19">3.6.4 Convert VMware disk images to raw disk images</A></H3>
+
+<P>
+You can use the tool <TT>`vmdk2raw'</TT> to convert VMware disk images to
+raw disk images directly usable by QEMU. The syntax is:
+
+<PRE>
+vmdk2raw vmware_image output_image
+</PRE>
+
+
+
+<H2><A NAME="SEC20" HREF="qemu-doc.html#TOC20">3.7 Network emulation</A></H2>
+
+<P>
+QEMU simulates up to 6 networks cards (NE2000 boards). Each card can
+be connected to a specific host network interface.
+
+
+
+
+<H3><A NAME="SEC21" HREF="qemu-doc.html#TOC21">3.7.1 Using tun/tap network interface</A></H3>
+
+<P>
+This is the standard way to emulate network. QEMU adds a virtual
+network device on your host (called <CODE>tun0</CODE>), and you can then
+configure it as if it was a real ethernet card.
+
+
+<P>
+As an example, you can download the <TT>`linux-test-xxx.tar.gz'</TT>
+archive and copy the script <TT>`qemu-ifup'</TT> in <TT>`/etc'</TT> and
+configure properly <CODE>sudo</CODE> so that the command <CODE>ifconfig</CODE>
+contained in <TT>`qemu-ifup'</TT> can be executed as root. You must verify
+that your host kernel supports the TUN/TAP network interfaces: the
+device <TT>`/dev/net/tun'</TT> must be present.
+
+
+<P>
+See section <A HREF="qemu-doc.html#SEC23">3.8 Direct Linux Boot</A> to have an example of network use with a
+Linux distribution.
+
+
+
+
+<H3><A NAME="SEC22" HREF="qemu-doc.html#TOC22">3.7.2 Using the user mode network stack</A></H3>
+
+<P>
+By using the option @option{-user-net} or if you have no tun/tap init
+script, QEMU uses a completely user mode network stack (you don't need
+root priviledge to use the virtual network). The virtual network
+configuration is the following:
+
+
+
+<PRE>
+
+QEMU Virtual Machine <------> Firewall/DHCP server <-----> Internet
+ (10.0.2.x) | (10.0.2.2)
+ |
+ ----> DNS server (10.0.2.3)
+ |
+ ----> SMB server (10.0.2.4)
+</PRE>
+
+<P>
+The QEMU VM behaves as if it was behind a firewall which blocks all
+incoming connections. You can use a DHCP client to automatically
+configure the network in the QEMU VM.
+
+
+<P>
+In order to check that the user mode network is working, you can ping
+the address 10.0.2.2 and verify that you got an address in the range
+10.0.2.x from the QEMU virtual DHCP server.
+
+
+<P>
+Note that <CODE>ping</CODE> is not supported reliably to the internet as it
+would require root priviledges. It means you can only ping the local
+router (10.0.2.2).
+
+
+<P>
+When using the built-in TFTP server, the router is also the TFTP
+server.
+
+
+<P>
+When using the @option{-redir} option, TCP or UDP connections can be
+redirected from the host to the guest. It allows for example to
+redirect X11, telnet or SSH connections.
+
+
+
+
+<H2><A NAME="SEC23" HREF="qemu-doc.html#TOC23">3.8 Direct Linux Boot</A></H2>
+
+<P>
+This section explains how to launch a Linux kernel inside QEMU without
+having to make a full bootable image. It is very useful for fast Linux
+kernel testing. The QEMU network configuration is also explained.
+
+
+
+<OL>
+<LI>
+
+Download the archive <TT>`linux-test-xxx.tar.gz'</TT> containing a Linux
+kernel and a disk image.
+
+<LI>Optional: If you want network support (for example to launch X11 examples), you
+
+must copy the script <TT>`qemu-ifup'</TT> in <TT>`/etc'</TT> and configure
+properly <CODE>sudo</CODE> so that the command <CODE>ifconfig</CODE> contained in
+<TT>`qemu-ifup'</TT> can be executed as root. You must verify that your host
+kernel supports the TUN/TAP network interfaces: the device
+<TT>`/dev/net/tun'</TT> must be present.
+
+When network is enabled, there is a virtual network connection between
+the host kernel and the emulated kernel. The emulated kernel is seen
+from the host kernel at IP address 172.20.0.2 and the host kernel is
+seen from the emulated kernel at IP address 172.20.0.1.
+
+<LI>Launch <CODE>qemu.sh</CODE>. You should have the following output:
+
+
+<PRE>
+> ./qemu.sh
+Connected to host network interface: tun0
+Linux version 2.4.21 (bellard@voyager.localdomain) (gcc version 3.2.2 20030222 (Red Hat Linux 3.2.2-5)) #5 Tue Nov 11 18:18:53 CET 2003
+BIOS-provided physical RAM map:
+ BIOS-e801: 0000000000000000 - 000000000009f000 (usable)
+ BIOS-e801: 0000000000100000 - 0000000002000000 (usable)
+32MB LOWMEM available.
+On node 0 totalpages: 8192
+zone(0): 4096 pages.
+zone(1): 4096 pages.
+zone(2): 0 pages.
+Kernel command line: root=/dev/hda sb=0x220,5,1,5 ide2=noprobe ide3=noprobe ide4=noprobe ide5=noprobe console=ttyS0
+ide_setup: ide2=noprobe
+ide_setup: ide3=noprobe
+ide_setup: ide4=noprobe
+ide_setup: ide5=noprobe
+Initializing CPU#0
+Detected 2399.621 MHz processor.
+Console: colour EGA 80x25
+Calibrating delay loop... 4744.80 BogoMIPS
+Memory: 28872k/32768k available (1210k kernel code, 3508k reserved, 266k data, 64k init, 0k highmem)
+Dentry cache hash table entries: 4096 (order: 3, 32768 bytes)
+Inode cache hash table entries: 2048 (order: 2, 16384 bytes)
+Mount cache hash table entries: 512 (order: 0, 4096 bytes)
+Buffer-cache hash table entries: 1024 (order: 0, 4096 bytes)
+Page-cache hash table entries: 8192 (order: 3, 32768 bytes)
+CPU: Intel Pentium Pro stepping 03
+Checking 'hlt' instruction... OK.
+POSIX conformance testing by UNIFIX
+Linux NET4.0 for Linux 2.4
+Based upon Swansea University Computer Society NET3.039
+Initializing RT netlink socket
+apm: BIOS not found.
+Starting kswapd
+Journalled Block Device driver loaded
+Detected PS/2 Mouse Port.
+pty: 256 Unix98 ptys configured
+Serial driver version 5.05c (2001-07-08) with no serial options enabled
+ttyS00 at 0x03f8 (irq = 4) is a 16450
+ne.c:v1.10 9/23/94 Donald Becker (becker@scyld.com)
+Last modified Nov 1, 2000 by Paul Gortmaker
+NE*000 ethercard probe at 0x300: 52 54 00 12 34 56
+eth0: NE2000 found at 0x300, using IRQ 9.
+RAMDISK driver initialized: 16 RAM disks of 4096K size 1024 blocksize
+Uniform Multi-Platform E-IDE driver Revision: 7.00beta4-2.4
+ide: Assuming 50MHz system bus speed for PIO modes; override with idebus=xx
+hda: QEMU HARDDISK, ATA DISK drive
+ide0 at 0x1f0-0x1f7,0x3f6 on irq 14
+hda: attached ide-disk driver.
+hda: 20480 sectors (10 MB) w/256KiB Cache, CHS=20/16/63
+Partition check:
+ hda:
+Soundblaster audio driver Copyright (C) by Hannu Savolainen 1993-1996
+NET4: Linux TCP/IP 1.0 for NET4.0
+IP Protocols: ICMP, UDP, TCP, IGMP
+IP: routing cache hash table of 512 buckets, 4Kbytes
+TCP: Hash tables configured (established 2048 bind 4096)
+NET4: Unix domain sockets 1.0/SMP for Linux NET4.0.
+EXT2-fs warning: mounting unchecked fs, running e2fsck is recommended
+VFS: Mounted root (ext2 filesystem).
+Freeing unused kernel memory: 64k freed
+
+Linux version 2.4.21 (bellard@voyager.localdomain) (gcc version 3.2.2 20030222 (Red Hat Linux 3.2.2-5)) #5 Tue Nov 11 18:18:53 CET 2003
+
+QEMU Linux test distribution (based on Redhat 9)
+
+Type 'exit' to halt the system
+
+sh-2.05b#
+</PRE>
+
+<LI>
+
+Then you can play with the kernel inside the virtual serial console. You
+can launch <CODE>ls</CODE> for example. Type <KBD>Ctrl-a h</KBD> to have an help
+about the keys you can type inside the virtual serial console. In
+particular, use <KBD>Ctrl-a x</KBD> to exit QEMU and use <KBD>Ctrl-a b</KBD> as
+the Magic SysRq key.
+
+<LI>
+
+If the network is enabled, launch the script <TT>`/etc/linuxrc'</TT> in the
+emulator (don't forget the leading dot):
+
+<PRE>
+. /etc/linuxrc
+</PRE>
+
+Then enable X11 connections on your PC from the emulated Linux:
+
+<PRE>
+xhost +172.20.0.2
+</PRE>
+
+You can now launch <TT>`xterm'</TT> or <TT>`xlogo'</TT> and verify that you have
+a real Virtual Linux system !
+
+</OL>
+
+<P>
+NOTES:
+
+<OL>
+<LI>
+
+A 2.5.74 kernel is also included in the archive. Just
+replace the bzImage in qemu.sh to try it.
+
+<LI>
+
+qemu-fast creates a temporary file in <VAR>$QEMU_TMPDIR</VAR> (<TT>`/tmp'</TT> is the
+default) containing all the simulated PC memory. If possible, try to use
+a temporary directory using the tmpfs filesystem to avoid too many
+unnecessary disk accesses.
+
+<LI>
+
+In order to exit cleanly from qemu, you can do a <EM>shutdown</EM> inside
+qemu. qemu will automatically exit when the Linux shutdown is done.
+
+<LI>
+
+You can boot slightly faster by disabling the probe of non present IDE
+interfaces. To do so, add the following options on the kernel command
+line:
+
+<PRE>
+ide1=noprobe ide2=noprobe ide3=noprobe ide4=noprobe ide5=noprobe
+</PRE>
+
+<LI>
+
+The example disk image is a modified version of the one made by Kevin
+Lawton for the plex86 Project (<A HREF="www.plex86.org">www.plex86.org</A>).
+
+</OL>
+
+
+
+<H2><A NAME="SEC24" HREF="qemu-doc.html#TOC24">3.9 Linux Kernel Compilation</A></H2>
+
+<P>
+You can use any linux kernel with QEMU. However, if you want to use
+<CODE>qemu-fast</CODE> to get maximum performances, you must use a modified
+guest kernel. If you are using a 2.6 guest kernel, you can use
+directly the patch <TT>`linux-2.6-qemu-fast.patch'</TT> made by Rusty
+Russel available in the QEMU source archive. Otherwise, you can make the
+following changes <EM>by hand</EM> to the Linux kernel:
+
+
+
+<OL>
+<LI>
+
+The kernel must be mapped at 0x90000000 (the default is
+0xc0000000). You must modify only two lines in the kernel source:
+
+In <TT>`include/asm/page.h'</TT>, replace
+
+<PRE>
+#define __PAGE_OFFSET (0xc0000000)
+</PRE>
+
+by
+
+<PRE>
+#define __PAGE_OFFSET (0x90000000)
+</PRE>
+
+And in <TT>`arch/i386/vmlinux.lds'</TT>, replace
+
+<PRE>
+ . = 0xc0000000 + 0x100000;
+</PRE>
+
+by
+
+<PRE>
+ . = 0x90000000 + 0x100000;
+</PRE>
+
+<LI>
+
+If you want to enable SMP (Symmetric Multi-Processing) support, you
+must make the following change in <TT>`include/asm/fixmap.h'</TT>. Replace
+
+<PRE>
+#define FIXADDR_TOP (0xffffX000UL)
+</PRE>
+
+by
+
+<PRE>
+#define FIXADDR_TOP (0xa7ffX000UL)
+</PRE>
+
+(X is 'e' or 'f' depending on the kernel version). Although you can
+use an SMP kernel with QEMU, it only supports one CPU.
+
+<LI>
+
+If you are not using a 2.6 kernel as host kernel but if you use a target
+2.6 kernel, you must also ensure that the 'HZ' define is set to 100
+(1000 is the default) as QEMU cannot currently emulate timers at
+frequencies greater than 100 Hz on host Linux systems < 2.6. In
+<TT>`include/asm/param.h'</TT>, replace:
+
+
+<PRE>
+# define HZ 1000 /* Internal kernel timer frequency */
+</PRE>
+
+by
+
+<PRE>
+# define HZ 100 /* Internal kernel timer frequency */
+</PRE>
+
+</OL>
+
+<P>
+The file config-2.x.x gives the configuration of the example kernels.
+
+
+<P>
+Just type
+
+<PRE>
+make bzImage
+</PRE>
+
+<P>
+As you would do to make a real kernel. Then you can use with QEMU
+exactly the same kernel as you would boot on your PC (in
+<TT>`arch/i386/boot/bzImage'</TT>).
+
+
+
+
+<H2><A NAME="SEC25" HREF="qemu-doc.html#TOC25">3.10 GDB usage</A></H2>
+
+<P>
+QEMU has a primitive support to work with gdb, so that you can do
+'Ctrl-C' while the virtual machine is running and inspect its state.
+
+
+<P>
+In order to use gdb, launch qemu with the '-s' option. It will wait for a
+gdb connection:
+
+<PRE>
+> qemu -s -kernel arch/i386/boot/bzImage -hda root-2.4.20.img -append "root=/dev/hda"
+Connected to host network interface: tun0
+Waiting gdb connection on port 1234
+</PRE>
+
+<P>
+Then launch gdb on the 'vmlinux' executable:
+
+<PRE>
+> gdb vmlinux
+</PRE>
+
+<P>
+In gdb, connect to QEMU:
+
+<PRE>
+(gdb) target remote localhost:1234
+</PRE>
+
+<P>
+Then you can use gdb normally. For example, type 'c' to launch the kernel:
+
+<PRE>
+(gdb) c
+</PRE>
+
+<P>
+Here are some useful tips in order to use gdb on system code:
+
+
+
+<OL>
+<LI>
+
+Use <CODE>info reg</CODE> to display all the CPU registers.
+<LI>
+
+Use <CODE>x/10i $eip</CODE> to display the code at the PC position.
+<LI>
+
+Use <CODE>set architecture i8086</CODE> to dump 16 bit code. Then use
+<CODE>x/10i $cs*16+*eip</CODE> to dump the code at the PC position.
+</OL>
+
+
+
+<H2><A NAME="SEC26" HREF="qemu-doc.html#TOC26">3.11 Target OS specific information</A></H2>
+
+
+
+<H3><A NAME="SEC27" HREF="qemu-doc.html#TOC27">3.11.1 Linux</A></H3>
+
+<P>
+To have access to SVGA graphic modes under X11, use the <CODE>vesa</CODE> or
+the <CODE>cirrus</CODE> X11 driver. For optimal performances, use 16 bit
+color depth in the guest and the host OS.
+
+
+<P>
+When using a 2.6 guest Linux kernel, you should add the option
+<CODE>clock=pit</CODE> on the kernel command line because the 2.6 Linux
+kernels make very strict real time clock checks by default that QEMU
+cannot simulate exactly.
+
+
+
+
+<H3><A NAME="SEC28" HREF="qemu-doc.html#TOC28">3.11.2 Windows</A></H3>
+
+<P>
+If you have a slow host, using Windows 95 is better as it gives the
+best speed. Windows 2000 is also a good choice.
+
+
+
+
+<H4><A NAME="SEC29" HREF="qemu-doc.html#TOC29">3.11.2.1 SVGA graphic modes support</A></H4>
+
+<P>
+QEMU emulates a Cirrus Logic GD5446 Video
+card. All Windows versions starting from Windows 95 should recognize
+and use this graphic card. For optimal performances, use 16 bit color
+depth in the guest and the host OS.
+
+
+
+
+<H4><A NAME="SEC30" HREF="qemu-doc.html#TOC30">3.11.2.2 CPU usage reduction</A></H4>
+
+<P>
+Windows 9x does not correctly use the CPU HLT
+instruction. The result is that it takes host CPU cycles even when
+idle. You can install the utility from
+<A HREF="http://www.user.cityline.ru/~maxamn/amnhltm.zip">http://www.user.cityline.ru/~maxamn/amnhltm.zip</A> to solve this
+problem. Note that no such tool is needed for NT, 2000 or XP.
+
+
+
+
+<H4><A NAME="SEC31" HREF="qemu-doc.html#TOC31">3.11.2.3 Windows 2000 disk full problems</A></H4>
+
+<P>
+Currently (release 0.6.0) QEMU has a bug which gives a <CODE>disk
+full</CODE> error during installation of some releases of Windows 2000. The
+workaround is to stop QEMU as soon as you notice that your disk image
+size is growing too fast (monitor it with <CODE>ls -ls</CODE>). Then
+relaunch QEMU to continue the installation. If you still experience
+the problem, relaunch QEMU again.
+
+
+<P>
+Future QEMU releases are likely to correct this bug.
+
+
+
+
+<H4><A NAME="SEC32" HREF="qemu-doc.html#TOC32">3.11.2.4 Windows XP security problems</A></H4>
+
+<P>
+Some releases of Windows XP install correctly but give a security
+error when booting:
+
+<PRE>
+A problem is preventing Windows from accurately checking the
+license for this computer. Error code: 0x800703e6.
+</PRE>
+
+<P>
+The only known workaround is to boot in Safe mode
+without networking support.
+
+
+<P>
+Future QEMU releases are likely to correct this bug.
+
+
+
+
+<H3><A NAME="SEC33" HREF="qemu-doc.html#TOC33">3.11.3 MS-DOS and FreeDOS</A></H3>
+
+
+
+<H4><A NAME="SEC34" HREF="qemu-doc.html#TOC34">3.11.3.1 CPU usage reduction</A></H4>
+
+<P>
+DOS does not correctly use the CPU HLT instruction. The result is that
+it takes host CPU cycles even when idle. You can install the utility
+from <A HREF="http://www.vmware.com/software/dosidle210.zip">http://www.vmware.com/software/dosidle210.zip</A> to solve this
+problem.
+
+
+
+
+<H1><A NAME="SEC35" HREF="qemu-doc.html#TOC35">4. QEMU PowerPC System emulator invocation</A></H1>
+
+<P>
+Use the executable <TT>`qemu-system-ppc'</TT> to simulate a complete PREP
+or PowerMac PowerPC system.
+
+
+<P>
+QEMU emulates the following PowerMac peripherials:
+
+
+
+<UL>
+<LI>
+
+UniNorth PCI Bridge
+<LI>
+
+PCI VGA compatible card with VESA Bochs Extensions
+<LI>
+
+2 PMAC IDE interfaces with hard disk and CD-ROM support
+<LI>
+
+NE2000 PCI adapters
+<LI>
+
+Non Volatile RAM
+<LI>
+
+VIA-CUDA with ADB keyboard and mouse.
+</UL>
+
+<P>
+QEMU emulates the following PREP peripherials:
+
+
+
+<UL>
+<LI>
+
+PCI Bridge
+<LI>
+
+PCI VGA compatible card with VESA Bochs Extensions
+<LI>
+
+2 IDE interfaces with hard disk and CD-ROM support
+<LI>
+
+Floppy disk
+<LI>
+
+NE2000 network adapters
+<LI>
+
+Serial port
+<LI>
+
+PREP Non Volatile RAM
+<LI>
+
+PC compatible keyboard and mouse.
+</UL>
+
+<P>
+QEMU uses the Open Hack'Ware Open Firmware Compatible BIOS available at
+<A HREF="http://site.voila.fr/jmayer/OpenHackWare/index.htm">http://site.voila.fr/jmayer/OpenHackWare/index.htm</A>.
+
+
+<P>
+You can read the qemu PC system emulation chapter to have more
+informations about QEMU usage.
+
+
+<P>
+The following options are specific to the PowerPC emulation:
+
+
+<DL COMPACT>
+
+<DT>@option{-prep}
+<DD>
+Simulate a PREP system (default is PowerMAC)
+
+<DT>@option{-g WxH[xDEPTH]}
+<DD>
+Set the initial VGA graphic mode. The default is 800x600x15.
+
+</DL>
+
+<P>
+More information is available at
+<A HREF="http://jocelyn.mayer.free.fr/qemu-ppc/">http://jocelyn.mayer.free.fr/qemu-ppc/</A>.
+
+
+
+
+<H1><A NAME="SEC36" HREF="qemu-doc.html#TOC36">5. QEMU User space emulator invocation</A></H1>
+
+
+
+<H2><A NAME="SEC37" HREF="qemu-doc.html#TOC37">5.1 Quick Start</A></H2>
+
+<P>
+In order to launch a Linux process, QEMU needs the process executable
+itself and all the target (x86) dynamic libraries used by it.
+
+
+
+<UL>
+
+<LI>On x86, you can just try to launch any process by using the native
+
+libraries:
+
+
+<PRE>
+qemu-i386 -L / /bin/ls
+</PRE>
+
+<CODE>-L /</CODE> tells that the x86 dynamic linker must be searched with a
+<TT>`/'</TT> prefix.
+
+<LI>Since QEMU is also a linux process, you can launch qemu with qemu (NOTE: you can only do that if you compiled QEMU from the sources):
+
+
+<PRE>
+qemu-i386 -L / qemu-i386 -L / /bin/ls
+</PRE>
+
+<LI>On non x86 CPUs, you need first to download at least an x86 glibc
+
+(<TT>`qemu-runtime-i386-XXX-.tar.gz'</TT> on the QEMU web page). Ensure that
+<CODE>LD_LIBRARY_PATH</CODE> is not set:
+
+
+<PRE>
+unset LD_LIBRARY_PATH
+</PRE>
+
+Then you can launch the precompiled <TT>`ls'</TT> x86 executable:
+
+
+<PRE>
+qemu-i386 tests/i386/ls
+</PRE>
+
+You can look at <TT>`qemu-binfmt-conf.sh'</TT> so that
+QEMU is automatically launched by the Linux kernel when you try to
+launch x86 executables. It requires the <CODE>binfmt_misc</CODE> module in the
+Linux kernel.
+
+<LI>The x86 version of QEMU is also included. You can try weird things such as:
+
+
+<PRE>
+qemu-i386 /usr/local/qemu-i386/bin/qemu-i386 /usr/local/qemu-i386/bin/ls-i386
+</PRE>
+
+</UL>
+
+
+
+<H2><A NAME="SEC38" HREF="qemu-doc.html#TOC38">5.2 Wine launch</A></H2>
+
+
+<UL>
+
+<LI>Ensure that you have a working QEMU with the x86 glibc
+
+distribution (see previous section). In order to verify it, you must be
+able to do:
+
+
+<PRE>
+qemu-i386 /usr/local/qemu-i386/bin/ls-i386
+</PRE>
+
+<LI>Download the binary x86 Wine install
+
+(<TT>`qemu-XXX-i386-wine.tar.gz'</TT> on the QEMU web page).
+
+<LI>Configure Wine on your account. Look at the provided script
+
+<TT>`/usr/local/qemu-i386/bin/wine-conf.sh'</TT>. Your previous
+<CODE>${HOME}/.wine</CODE> directory is saved to <CODE>${HOME}/.wine.org</CODE>.
+
+<LI>Then you can try the example <TT>`putty.exe'</TT>:
+
+
+<PRE>
+qemu-i386 /usr/local/qemu-i386/wine/bin/wine /usr/local/qemu-i386/wine/c/Program\ Files/putty.exe
+</PRE>
+
+</UL>
+
+
+
+<H2><A NAME="SEC39" HREF="qemu-doc.html#TOC39">5.3 Command line options</A></H2>
+
+
+<PRE>
+usage: qemu-i386 [-h] [-d] [-L path] [-s size] program [arguments...]
+</PRE>
+
+<DL COMPACT>
+
+<DT>@option{-h}
+<DD>
+Print the help
+<DT>@option{-L path}
+<DD>
+Set the x86 elf interpreter prefix (default=/usr/local/qemu-i386)
+<DT>@option{-s size}
+<DD>
+Set the x86 stack size in bytes (default=524288)
+</DL>
+
+<P>
+Debug options:
+
+
+<DL COMPACT>
+
+<DT>@option{-d}
+<DD>
+Activate log (logfile=/tmp/qemu.log)
+<DT>@option{-p pagesize}
+<DD>
+Act as if the host page size was 'pagesize' bytes
+</DL>
+
+
+
+<H1><A NAME="SEC40" HREF="qemu-doc.html#TOC40">6. Compilation from the sources</A></H1>
+
+
+
+<H2><A NAME="SEC41" HREF="qemu-doc.html#TOC41">6.1 Linux/BSD</A></H2>
+
+<P>
+Read the <TT>`README'</TT> which gives the related information.
+
+
+
+
+<H2><A NAME="SEC42" HREF="qemu-doc.html#TOC42">6.2 Windows</A></H2>
+
+
+<UL>
+<LI>Install the current versions of MSYS and MinGW from
+
+<A HREF="http://www.mingw.org/">http://www.mingw.org/</A>. You can find detailed installation
+instructions in the download section and the FAQ.
+
+<LI>Download
+
+the MinGW development library of SDL 1.2.x
+(<TT>`SDL-devel-1.2.x-mingw32.tar.gz'</TT>) from
+<A HREF="http://www.libsdl.org">http://www.libsdl.org</A>. Unpack it in a temporary place, and
+unpack the archive <TT>`i386-mingw32msvc.tar.gz'</TT> in the MinGW tool
+directory. Edit the <TT>`sdl-config'</TT> script so that it gives the
+correct SDL directory when invoked.
+
+<LI>Extract the current version of QEMU.
+
+
+<LI>Start the MSYS shell (file <TT>`msys.bat'</TT>).
+
+<LI>Change to the QEMU directory. Launch <TT>`./configure'</TT> and
+
+<TT>`make'</TT>. If you have problems using SDL, verify that
+<TT>`sdl-config'</TT> can be launched from the MSYS command line.
+
+<LI>You can install QEMU in <TT>`Program Files/Qemu'</TT> by typing
+
+<TT>`make install'</TT>. Don't forget to copy <TT>`SDL.dll'</TT> in
+<TT>`Program Files/Qemu'</TT>.
+
+</UL>
+
+
+
+<H2><A NAME="SEC43" HREF="qemu-doc.html#TOC43">6.3 Cross compilation for Windows with Linux</A></H2>
+
+
+<UL>
+<LI>
+
+Install the MinGW cross compilation tools available at
+<A HREF="http://www.mingw.org/">http://www.mingw.org/</A>.
+
+<LI>
+
+Install the Win32 version of SDL (<A HREF="http://www.libsdl.org">http://www.libsdl.org</A>) by
+unpacking <TT>`i386-mingw32msvc.tar.gz'</TT>. Set up the PATH environment
+variable so that <TT>`i386-mingw32msvc-sdl-config'</TT> can be launched by
+the QEMU configuration script.
+
+<LI>
+
+Configure QEMU for Windows cross compilation:
+
+<PRE>
+./configure --enable-mingw32
+</PRE>
+
+If necessary, you can change the cross-prefix according to the prefix
+choosen for the MinGW tools with --cross-prefix. You can also use
+--prefix to set the Win32 install path.
+
+<LI>You can install QEMU in the installation directory by typing
+
+<TT>`make install'</TT>. Don't forget to copy <TT>`SDL.dll'</TT> in the
+installation directory.
+
+</UL>
+
+<P>
+Note: Currently, Wine does not seem able to launch
+QEMU for Win32.
+
+
+
+
+<H2><A NAME="SEC44" HREF="qemu-doc.html#TOC44">6.4 Mac OS X</A></H2>
+
+<P>
+The Mac OS X patches are not fully merged in QEMU, so you should look
+at the QEMU mailing list archive to have all the necessary
+information.
+
+
+<P><HR><P>
+This document was generated on 19 May 2005 using
+<A HREF="http://wwwinfo.cern.ch/dis/texi2html/">texi2html</A> 1.56k.
+</BODY>
+</HTML>
--- /dev/null
+\input texinfo @c -*- texinfo -*-
+
+@iftex
+@settitle QEMU CPU Emulator User Documentation
+@titlepage
+@sp 7
+@center @titlefont{QEMU CPU Emulator User Documentation}
+@sp 3
+@end titlepage
+@end iftex
+
+@chapter Introduction
+
+@section Features
+
+QEMU is a FAST! processor emulator using dynamic translation to
+achieve good emulation speed.
+
+QEMU has two operating modes:
+
+@itemize @minus
+
+@item
+Full system emulation. In this mode, QEMU emulates a full system (for
+example a PC), including a processor and various peripherials. It can
+be used to launch different Operating Systems without rebooting the
+PC or to debug system code.
+
+@item
+User mode emulation (Linux host only). In this mode, QEMU can launch
+Linux processes compiled for one CPU on another CPU. It can be used to
+launch the Wine Windows API emulator (@url{http://www.winehq.org}) or
+to ease cross-compilation and cross-debugging.
+
+@end itemize
+
+As QEMU requires no host kernel driver to run, it is very safe and
+easy to use.
+
+For system emulation, the following hardware targets are supported:
+@itemize
+@item PC (x86 processor)
+@item PREP (PowerPC processor)
+@item PowerMac (PowerPC processor, in progress)
+@end itemize
+
+For user emulation, x86, PowerPC, ARM, and SPARC CPUs are supported.
+
+@chapter Installation
+
+If you want to compile QEMU yourself, see @ref{compilation}.
+
+@section Linux
+
+Download the binary distribution (@file{qemu-XXX-i386.tar.gz}) and
+untar it as root in @file{/}:
+
+@example
+su
+cd /
+tar zxvf /tmp/qemu-XXX-i386.tar.gz
+@end example
+
+@section Windows
+
+Download the experimental binary installer at
+@url{http://www.freeoszoo.org/download.php}.
+
+@section Mac OS X
+
+Download the experimental binary installer at
+@url{http://www.freeoszoo.org/download.php}.
+
+@chapter QEMU PC System emulator invocation
+
+@section Introduction
+
+@c man begin DESCRIPTION
+
+The QEMU System emulator simulates a complete PC.
+
+In order to meet specific user needs, two versions of QEMU are
+available:
+
+@enumerate
+
+@item
+@code{qemu-fast} uses the host Memory Management Unit (MMU) to
+simulate the x86 MMU. It is @emph{fast} but has limitations because
+the whole 4 GB address space cannot be used and some memory mapped
+peripherials cannot be emulated accurately yet. Therefore, a specific
+guest Linux kernel can be used (@xref{linux_compile}) as guest
+OS.
+
+Moreover there is no separation between the host and target address
+spaces, so it offers no security (the target OS can modify the
+@code{qemu-fast} code by writing at the right addresses).
+
+@item
+@code{qemu} uses a software MMU. It is about @emph{two times slower}
+but gives a more accurate emulation and a complete separation between
+the host and target address spaces.
+
+@end enumerate
+
+QEMU emulates the following PC peripherials:
+
+@itemize @minus
+@item
+i440FX host PCI bridge and PIIX3 PCI to ISA bridge
+@item
+Cirrus CLGD 5446 PCI VGA card or dummy VGA card with Bochs VESA
+extensions (hardware level, including all non standard modes).
+@item
+PS/2 mouse and keyboard
+@item
+2 PCI IDE interfaces with hard disk and CD-ROM support
+@item
+Floppy disk
+@item
+NE2000 PCI network adapters
+@item
+Serial ports
+@item
+Soundblaster 16 card
+@end itemize
+
+QEMU uses the PC BIOS from the Bochs project and the Plex86/Bochs LGPL
+VGA BIOS.
+
+@c man end
+
+@section Quick Start
+
+Download and uncompress the linux image (@file{linux.img}) and type:
+
+@example
+qemu linux.img
+@end example
+
+Linux should boot and give you a prompt.
+
+@section Invocation
+
+@example
+@c man begin SYNOPSIS
+usage: qemu [options] [disk_image]
+@c man end
+@end example
+
+@c man begin OPTIONS
+@var{disk_image} is a raw hard disk image for IDE hard disk 0.
+
+General options:
+@table @option
+@item -fda file
+@item -fdb file
+Use @var{file} as floppy disk 0/1 image (@xref{disk_images}). You can
+use the host floppy by using @file{/dev/fd0} as filename.
+
+@item -hda file
+@item -hdb file
+@item -hdc file
+@item -hdd file
+Use @var{file} as hard disk 0, 1, 2 or 3 image (@xref{disk_images}).
+
+@item -cdrom file
+Use @var{file} as CD-ROM image (you cannot use @option{-hdc} and and
+@option{-cdrom} at the same time). You can use the host CD-ROM by
+using @file{/dev/cdrom} as filename.
+
+@item -boot [a|c|d]
+Boot on floppy (a), hard disk (c) or CD-ROM (d). Hard disk boot is
+the default.
+
+@item -snapshot
+Write to temporary files instead of disk image files. In this case,
+the raw disk image you use is not written back. You can however force
+the write back by pressing @key{C-a s} (@xref{disk_images}).
+
+@item -m megs
+Set virtual RAM size to @var{megs} megabytes. Default is 128 MB.
+
+@item -nographic
+
+Normally, QEMU uses SDL to display the VGA output. With this option,
+you can totally disable graphical output so that QEMU is a simple
+command line application. The emulated serial port is redirected on
+the console. Therefore, you can still use QEMU to debug a Linux kernel
+with a serial console.
+
+@item -enable-audio
+
+The SB16 emulation is disabled by default as it may give problems with
+Windows. You can enable it manually with this option.
+
+@item -localtime
+Set the real time clock to local time (the default is to UTC
+time). This option is needed to have correct date in MS-DOS or
+Windows.
+
+@item -full-screen
+Start in full screen.
+
+@end table
+
+Network options:
+
+@table @option
+
+@item -n script
+Set TUN/TAP network init script [default=/etc/qemu-ifup]. This script
+is launched to configure the host network interface (usually tun0)
+corresponding to the virtual NE2000 card.
+
+@item -macaddr addr
+
+Set the mac address of the first interface (the format is
+aa:bb:cc:dd:ee:ff in hexa). The mac address is incremented for each
+new network interface.
+
+@item -tun-fd fd
+Assumes @var{fd} talks to a tap/tun host network interface and use
+it. Read @url{http://bellard.org/qemu/tetrinet.html} to have an
+example of its use.
+
+@item -user-net
+Use the user mode network stack. This is the default if no tun/tap
+network init script is found.
+
+@item -tftp prefix
+When using the user mode network stack, activate a built-in TFTP
+server. All filenames beginning with @var{prefix} can be downloaded
+from the host to the guest using a TFTP client. The TFTP client on the
+guest must be configured in binary mode (use the command @code{bin} of
+the Unix TFTP client). The host IP address on the guest is as usual
+10.0.2.2.
+
+@item -smb dir
+When using the user mode network stack, activate a built-in SMB
+server so that Windows OSes can access to the host files in @file{dir}
+transparently.
+
+In the guest Windows OS, the line:
+@example
+10.0.2.4 smbserver
+@end example
+must be added in the file @file{C:\WINDOWS\LMHOSTS} (for windows 9x/Me)
+or @file{C:\WINNT\SYSTEM32\DRIVERS\ETC\LMHOSTS} (Windows NT/2000).
+
+Then @file{dir} can be accessed in @file{\\smbserver\qemu}.
+
+Note that a SAMBA server must be installed on the host OS in
+@file{/usr/sbin/smbd}. QEMU was tested succesfully with smbd version
+2.2.7a from the Red Hat 9.
+
+@item -redir [tcp|udp]:host-port:[guest-host]:guest-port
+
+When using the user mode network stack, redirect incoming TCP or UDP
+connections to the host port @var{host-port} to the guest
+@var{guest-host} on guest port @var{guest-port}. If @var{guest-host}
+is not specified, its value is 10.0.2.15 (default address given by the
+built-in DHCP server).
+
+For example, to redirect host X11 connection from screen 1 to guest
+screen 0, use the following:
+
+@example
+# on the host
+qemu -redir tcp:6001::6000 [...]
+# this host xterm should open in the guest X11 server
+xterm -display :1
+@end example
+
+To redirect telnet connections from host port 5555 to telnet port on
+the guest, use the following:
+
+@example
+# on the host
+qemu -redir tcp:5555::23 [...]
+telnet localhost 5555
+@end example
+
+Then when you use on the host @code{telnet localhost 5555}, you
+connect to the guest telnet server.
+
+@item -dummy-net
+Use the dummy network stack: no packet will be received by the network
+cards.
+
+@end table
+
+Linux boot specific. When using this options, you can use a given
+Linux kernel without installing it in the disk image. It can be useful
+for easier testing of various kernels.
+
+@table @option
+
+@item -kernel bzImage
+Use @var{bzImage} as kernel image.
+
+@item -append cmdline
+Use @var{cmdline} as kernel command line
+
+@item -initrd file
+Use @var{file} as initial ram disk.
+
+@end table
+
+Debug/Expert options:
+@table @option
+
+@item -serial dev
+Redirect the virtual serial port to host device @var{dev}. Available
+devices are:
+@table @code
+@item vc
+Virtual console
+@item pty
+[Linux only] Pseudo TTY (a new PTY is automatically allocated)
+@item null
+void device
+@item stdio
+[Unix only] standard input/output
+@end table
+The default device is @code{vc} in graphical mode and @code{stdio} in
+non graphical mode.
+
+This option can be used several times to simulate up to 4 serials
+ports.
+
+@item -monitor dev
+Redirect the monitor to host device @var{dev} (same devices as the
+serial port).
+The default device is @code{vc} in graphical mode and @code{stdio} in
+non graphical mode.
+
+@item -s
+Wait gdb connection to port 1234 (@xref{gdb_usage}).
+@item -p port
+Change gdb connection port.
+@item -S
+Do not start CPU at startup (you must type 'c' in the monitor).
+@item -d
+Output log in /tmp/qemu.log
+@item -isa
+Simulate an ISA-only system (default is PCI system).
+@item -std-vga
+Simulate a standard VGA card with Bochs VBE extensions (default is
+Cirrus Logic GD5446 PCI VGA)
+@item -loadvm file
+Start right away with a saved state (@code{loadvm} in monitor)
+@end table
+
+@c man end
+
+@section Keys
+
+@c man begin OPTIONS
+
+During the graphical emulation, you can use the following keys:
+@table @key
+@item Ctrl-Alt-f
+Toggle full screen
+
+@item Ctrl-Alt-n
+Switch to virtual console 'n'. Standard console mappings are:
+@table @emph
+@item 1
+Target system display
+@item 2
+Monitor
+@item 3
+Serial port
+@end table
+
+@item Ctrl-Alt
+Toggle mouse and keyboard grab.
+@end table
+
+In the virtual consoles, you can use @key{Ctrl-Up}, @key{Ctrl-Down},
+@key{Ctrl-PageUp} and @key{Ctrl-PageDown} to move in the back log.
+
+During emulation, if you are using the @option{-nographic} option, use
+@key{Ctrl-a h} to get terminal commands:
+
+@table @key
+@item Ctrl-a h
+Print this help
+@item Ctrl-a x
+Exit emulatior
+@item Ctrl-a s
+Save disk data back to file (if -snapshot)
+@item Ctrl-a b
+Send break (magic sysrq in Linux)
+@item Ctrl-a c
+Switch between console and monitor
+@item Ctrl-a Ctrl-a
+Send Ctrl-a
+@end table
+@c man end
+
+@ignore
+
+@setfilename qemu
+@settitle QEMU System Emulator
+
+@c man begin SEEALSO
+The HTML documentation of QEMU for more precise information and Linux
+user mode emulator invocation.
+@c man end
+
+@c man begin AUTHOR
+Fabrice Bellard
+@c man end
+
+@end ignore
+
+@end ignore
+
+
+@section QEMU Monitor
+
+The QEMU monitor is used to give complex commands to the QEMU
+emulator. You can use it to:
+
+@itemize @minus
+
+@item
+Remove or insert removable medias images
+(such as CD-ROM or floppies)
+
+@item
+Freeze/unfreeze the Virtual Machine (VM) and save or restore its state
+from a disk file.
+
+@item Inspect the VM state without an external debugger.
+
+@end itemize
+
+@subsection Commands
+
+The following commands are available:
+
+@table @option
+
+@item help or ? [cmd]
+Show the help for all commands or just for command @var{cmd}.
+
+@item commit
+Commit changes to the disk images (if -snapshot is used)
+
+@item info subcommand
+show various information about the system state
+
+@table @option
+@item info network
+show the network state
+@item info block
+show the block devices
+@item info registers
+show the cpu registers
+@item info history
+show the command line history
+@end table
+
+@item q or quit
+Quit the emulator.
+
+@item eject [-f] device
+Eject a removable media (use -f to force it).
+
+@item change device filename
+Change a removable media.
+
+@item screendump filename
+Save screen into PPM image @var{filename}.
+
+@item log item1[,...]
+Activate logging of the specified items to @file{/tmp/qemu.log}.
+
+@item savevm filename
+Save the whole virtual machine state to @var{filename}.
+
+@item loadvm filename
+Restore the whole virtual machine state from @var{filename}.
+
+@item stop
+Stop emulation.
+
+@item c or cont
+Resume emulation.
+
+@item gdbserver [port]
+Start gdbserver session (default port=1234)
+
+@item x/fmt addr
+Virtual memory dump starting at @var{addr}.
+
+@item xp /fmt addr
+Physical memory dump starting at @var{addr}.
+
+@var{fmt} is a format which tells the command how to format the
+data. Its syntax is: @option{/@{count@}@{format@}@{size@}}
+
+@table @var
+@item count
+is the number of items to be dumped.
+
+@item format
+can be x (hexa), d (signed decimal), u (unsigned decimal), o (octal),
+c (char) or i (asm instruction).
+
+@item size
+can be b (8 bits), h (16 bits), w (32 bits) or g (64 bits). On x86,
+@code{h} or @code{w} can be specified with the @code{i} format to
+respectively select 16 or 32 bit code instruction size.
+
+@end table
+
+Examples:
+@itemize
+@item
+Dump 10 instructions at the current instruction pointer:
+@example
+(qemu) x/10i $eip
+0x90107063: ret
+0x90107064: sti
+0x90107065: lea 0x0(%esi,1),%esi
+0x90107069: lea 0x0(%edi,1),%edi
+0x90107070: ret
+0x90107071: jmp 0x90107080
+0x90107073: nop
+0x90107074: nop
+0x90107075: nop
+0x90107076: nop
+@end example
+
+@item
+Dump 80 16 bit values at the start of the video memory.
+@example
+(qemu) xp/80hx 0xb8000
+0x000b8000: 0x0b50 0x0b6c 0x0b65 0x0b78 0x0b38 0x0b36 0x0b2f 0x0b42
+0x000b8010: 0x0b6f 0x0b63 0x0b68 0x0b73 0x0b20 0x0b56 0x0b47 0x0b41
+0x000b8020: 0x0b42 0x0b69 0x0b6f 0x0b73 0x0b20 0x0b63 0x0b75 0x0b72
+0x000b8030: 0x0b72 0x0b65 0x0b6e 0x0b74 0x0b2d 0x0b63 0x0b76 0x0b73
+0x000b8040: 0x0b20 0x0b30 0x0b35 0x0b20 0x0b4e 0x0b6f 0x0b76 0x0b20
+0x000b8050: 0x0b32 0x0b30 0x0b30 0x0b33 0x0720 0x0720 0x0720 0x0720
+0x000b8060: 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720
+0x000b8070: 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720
+0x000b8080: 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720
+0x000b8090: 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720 0x0720
+@end example
+@end itemize
+
+@item p or print/fmt expr
+
+Print expression value. Only the @var{format} part of @var{fmt} is
+used.
+
+@item sendkey keys
+
+Send @var{keys} to the emulator. Use @code{-} to press several keys
+simultaneously. Example:
+@example
+sendkey ctrl-alt-f1
+@end example
+
+This command is useful to send keys that your graphical user interface
+intercepts at low level, such as @code{ctrl-alt-f1} in X Window.
+
+@item system_reset
+
+Reset the system.
+
+@end table
+
+@subsection Integer expressions
+
+The monitor understands integers expressions for every integer
+argument. You can use register names to get the value of specifics
+CPU registers by prefixing them with @emph{$}.
+
+@node disk_images
+@section Disk Images
+
+@subsection Raw disk images
+
+The disk images can simply be raw images of the hard disk. You can
+create them with the command:
+@example
+dd of=myimage bs=1024 seek=mysize count=0
+@end example
+where @var{myimage} is the image filename and @var{mysize} is its size
+in kilobytes.
+
+@subsection Snapshot mode
+
+If you use the option @option{-snapshot}, all disk images are
+considered as read only. When sectors in written, they are written in
+a temporary file created in @file{/tmp}. You can however force the
+write back to the raw disk images by pressing @key{C-a s}.
+
+NOTE: The snapshot mode only works with raw disk images.
+
+@subsection Copy On Write disk images
+
+QEMU also supports user mode Linux
+(@url{http://user-mode-linux.sourceforge.net/}) Copy On Write (COW)
+disk images. The COW disk images are much smaller than normal images
+as they store only modified sectors. They also permit the use of the
+same disk image template for many users.
+
+To create a COW disk images, use the command:
+
+@example
+qemu-mkcow -f myrawimage.bin mycowimage.cow
+@end example
+
+@file{myrawimage.bin} is a raw image you want to use as original disk
+image. It will never be written to.
+
+@file{mycowimage.cow} is the COW disk image which is created by
+@code{qemu-mkcow}. You can use it directly with the @option{-hdx}
+options. You must not modify the original raw disk image if you use
+COW images, as COW images only store the modified sectors from the raw
+disk image. QEMU stores the original raw disk image name and its
+modified time in the COW disk image so that chances of mistakes are
+reduced.
+
+If the raw disk image is not read-only, by pressing @key{C-a s} you
+can flush the COW disk image back into the raw disk image, as in
+snapshot mode.
+
+COW disk images can also be created without a corresponding raw disk
+image. It is useful to have a big initial virtual disk image without
+using much disk space. Use:
+
+@example
+qemu-mkcow mycowimage.cow 1024
+@end example
+
+to create a 1 gigabyte empty COW disk image.
+
+NOTES:
+@enumerate
+@item
+COW disk images must be created on file systems supporting
+@emph{holes} such as ext2 or ext3.
+@item
+Since holes are used, the displayed size of the COW disk image is not
+the real one. To know it, use the @code{ls -ls} command.
+@end enumerate
+
+@subsection Convert VMware disk images to raw disk images
+
+You can use the tool @file{vmdk2raw} to convert VMware disk images to
+raw disk images directly usable by QEMU. The syntax is:
+@example
+vmdk2raw vmware_image output_image
+@end example
+
+@section Network emulation
+
+QEMU simulates up to 6 networks cards (NE2000 boards). Each card can
+be connected to a specific host network interface.
+
+@subsection Using tun/tap network interface
+
+This is the standard way to emulate network. QEMU adds a virtual
+network device on your host (called @code{tun0}), and you can then
+configure it as if it was a real ethernet card.
+
+As an example, you can download the @file{linux-test-xxx.tar.gz}
+archive and copy the script @file{qemu-ifup} in @file{/etc} and
+configure properly @code{sudo} so that the command @code{ifconfig}
+contained in @file{qemu-ifup} can be executed as root. You must verify
+that your host kernel supports the TUN/TAP network interfaces: the
+device @file{/dev/net/tun} must be present.
+
+See @ref{direct_linux_boot} to have an example of network use with a
+Linux distribution.
+
+@subsection Using the user mode network stack
+
+By using the option @option{-user-net} or if you have no tun/tap init
+script, QEMU uses a completely user mode network stack (you don't need
+root priviledge to use the virtual network). The virtual network
+configuration is the following:
+
+@example
+
+QEMU Virtual Machine <------> Firewall/DHCP server <-----> Internet
+ (10.0.2.x) | (10.0.2.2)
+ |
+ ----> DNS server (10.0.2.3)
+ |
+ ----> SMB server (10.0.2.4)
+@end example
+
+The QEMU VM behaves as if it was behind a firewall which blocks all
+incoming connections. You can use a DHCP client to automatically
+configure the network in the QEMU VM.
+
+In order to check that the user mode network is working, you can ping
+the address 10.0.2.2 and verify that you got an address in the range
+10.0.2.x from the QEMU virtual DHCP server.
+
+Note that @code{ping} is not supported reliably to the internet as it
+would require root priviledges. It means you can only ping the local
+router (10.0.2.2).
+
+When using the built-in TFTP server, the router is also the TFTP
+server.
+
+When using the @option{-redir} option, TCP or UDP connections can be
+redirected from the host to the guest. It allows for example to
+redirect X11, telnet or SSH connections.
+
+@node direct_linux_boot
+@section Direct Linux Boot
+
+This section explains how to launch a Linux kernel inside QEMU without
+having to make a full bootable image. It is very useful for fast Linux
+kernel testing. The QEMU network configuration is also explained.
+
+@enumerate
+@item
+Download the archive @file{linux-test-xxx.tar.gz} containing a Linux
+kernel and a disk image.
+
+@item Optional: If you want network support (for example to launch X11 examples), you
+must copy the script @file{qemu-ifup} in @file{/etc} and configure
+properly @code{sudo} so that the command @code{ifconfig} contained in
+@file{qemu-ifup} can be executed as root. You must verify that your host
+kernel supports the TUN/TAP network interfaces: the device
+@file{/dev/net/tun} must be present.
+
+When network is enabled, there is a virtual network connection between
+the host kernel and the emulated kernel. The emulated kernel is seen
+from the host kernel at IP address 172.20.0.2 and the host kernel is
+seen from the emulated kernel at IP address 172.20.0.1.
+
+@item Launch @code{qemu.sh}. You should have the following output:
+
+@example
+> ./qemu.sh
+Connected to host network interface: tun0
+Linux version 2.4.21 (bellard@voyager.localdomain) (gcc version 3.2.2 20030222 (Red Hat Linux 3.2.2-5)) #5 Tue Nov 11 18:18:53 CET 2003
+BIOS-provided physical RAM map:
+ BIOS-e801: 0000000000000000 - 000000000009f000 (usable)
+ BIOS-e801: 0000000000100000 - 0000000002000000 (usable)
+32MB LOWMEM available.
+On node 0 totalpages: 8192
+zone(0): 4096 pages.
+zone(1): 4096 pages.
+zone(2): 0 pages.
+Kernel command line: root=/dev/hda sb=0x220,5,1,5 ide2=noprobe ide3=noprobe ide4=noprobe ide5=noprobe console=ttyS0
+ide_setup: ide2=noprobe
+ide_setup: ide3=noprobe
+ide_setup: ide4=noprobe
+ide_setup: ide5=noprobe
+Initializing CPU#0
+Detected 2399.621 MHz processor.
+Console: colour EGA 80x25
+Calibrating delay loop... 4744.80 BogoMIPS
+Memory: 28872k/32768k available (1210k kernel code, 3508k reserved, 266k data, 64k init, 0k highmem)
+Dentry cache hash table entries: 4096 (order: 3, 32768 bytes)
+Inode cache hash table entries: 2048 (order: 2, 16384 bytes)
+Mount cache hash table entries: 512 (order: 0, 4096 bytes)
+Buffer-cache hash table entries: 1024 (order: 0, 4096 bytes)
+Page-cache hash table entries: 8192 (order: 3, 32768 bytes)
+CPU: Intel Pentium Pro stepping 03
+Checking 'hlt' instruction... OK.
+POSIX conformance testing by UNIFIX
+Linux NET4.0 for Linux 2.4
+Based upon Swansea University Computer Society NET3.039
+Initializing RT netlink socket
+apm: BIOS not found.
+Starting kswapd
+Journalled Block Device driver loaded
+Detected PS/2 Mouse Port.
+pty: 256 Unix98 ptys configured
+Serial driver version 5.05c (2001-07-08) with no serial options enabled
+ttyS00 at 0x03f8 (irq = 4) is a 16450
+ne.c:v1.10 9/23/94 Donald Becker (becker@scyld.com)
+Last modified Nov 1, 2000 by Paul Gortmaker
+NE*000 ethercard probe at 0x300: 52 54 00 12 34 56
+eth0: NE2000 found at 0x300, using IRQ 9.
+RAMDISK driver initialized: 16 RAM disks of 4096K size 1024 blocksize
+Uniform Multi-Platform E-IDE driver Revision: 7.00beta4-2.4
+ide: Assuming 50MHz system bus speed for PIO modes; override with idebus=xx
+hda: QEMU HARDDISK, ATA DISK drive
+ide0 at 0x1f0-0x1f7,0x3f6 on irq 14
+hda: attached ide-disk driver.
+hda: 20480 sectors (10 MB) w/256KiB Cache, CHS=20/16/63
+Partition check:
+ hda:
+Soundblaster audio driver Copyright (C) by Hannu Savolainen 1993-1996
+NET4: Linux TCP/IP 1.0 for NET4.0
+IP Protocols: ICMP, UDP, TCP, IGMP
+IP: routing cache hash table of 512 buckets, 4Kbytes
+TCP: Hash tables configured (established 2048 bind 4096)
+NET4: Unix domain sockets 1.0/SMP for Linux NET4.0.
+EXT2-fs warning: mounting unchecked fs, running e2fsck is recommended
+VFS: Mounted root (ext2 filesystem).
+Freeing unused kernel memory: 64k freed
+
+Linux version 2.4.21 (bellard@voyager.localdomain) (gcc version 3.2.2 20030222 (Red Hat Linux 3.2.2-5)) #5 Tue Nov 11 18:18:53 CET 2003
+
+QEMU Linux test distribution (based on Redhat 9)
+
+Type 'exit' to halt the system
+
+sh-2.05b#
+@end example
+
+@item
+Then you can play with the kernel inside the virtual serial console. You
+can launch @code{ls} for example. Type @key{Ctrl-a h} to have an help
+about the keys you can type inside the virtual serial console. In
+particular, use @key{Ctrl-a x} to exit QEMU and use @key{Ctrl-a b} as
+the Magic SysRq key.
+
+@item
+If the network is enabled, launch the script @file{/etc/linuxrc} in the
+emulator (don't forget the leading dot):
+@example
+. /etc/linuxrc
+@end example
+
+Then enable X11 connections on your PC from the emulated Linux:
+@example
+xhost +172.20.0.2
+@end example
+
+You can now launch @file{xterm} or @file{xlogo} and verify that you have
+a real Virtual Linux system !
+
+@end enumerate
+
+NOTES:
+@enumerate
+@item
+A 2.5.74 kernel is also included in the archive. Just
+replace the bzImage in qemu.sh to try it.
+
+@item
+qemu-fast creates a temporary file in @var{$QEMU_TMPDIR} (@file{/tmp} is the
+default) containing all the simulated PC memory. If possible, try to use
+a temporary directory using the tmpfs filesystem to avoid too many
+unnecessary disk accesses.
+
+@item
+In order to exit cleanly from qemu, you can do a @emph{shutdown} inside
+qemu. qemu will automatically exit when the Linux shutdown is done.
+
+@item
+You can boot slightly faster by disabling the probe of non present IDE
+interfaces. To do so, add the following options on the kernel command
+line:
+@example
+ide1=noprobe ide2=noprobe ide3=noprobe ide4=noprobe ide5=noprobe
+@end example
+
+@item
+The example disk image is a modified version of the one made by Kevin
+Lawton for the plex86 Project (@url{www.plex86.org}).
+
+@end enumerate
+
+@node linux_compile
+@section Linux Kernel Compilation
+
+You can use any linux kernel with QEMU. However, if you want to use
+@code{qemu-fast} to get maximum performances, you must use a modified
+guest kernel. If you are using a 2.6 guest kernel, you can use
+directly the patch @file{linux-2.6-qemu-fast.patch} made by Rusty
+Russel available in the QEMU source archive. Otherwise, you can make the
+following changes @emph{by hand} to the Linux kernel:
+
+@enumerate
+@item
+The kernel must be mapped at 0x90000000 (the default is
+0xc0000000). You must modify only two lines in the kernel source:
+
+In @file{include/asm/page.h}, replace
+@example
+#define __PAGE_OFFSET (0xc0000000)
+@end example
+by
+@example
+#define __PAGE_OFFSET (0x90000000)
+@end example
+
+And in @file{arch/i386/vmlinux.lds}, replace
+@example
+ . = 0xc0000000 + 0x100000;
+@end example
+by
+@example
+ . = 0x90000000 + 0x100000;
+@end example
+
+@item
+If you want to enable SMP (Symmetric Multi-Processing) support, you
+must make the following change in @file{include/asm/fixmap.h}. Replace
+@example
+#define FIXADDR_TOP (0xffffX000UL)
+@end example
+by
+@example
+#define FIXADDR_TOP (0xa7ffX000UL)
+@end example
+(X is 'e' or 'f' depending on the kernel version). Although you can
+use an SMP kernel with QEMU, it only supports one CPU.
+
+@item
+If you are not using a 2.6 kernel as host kernel but if you use a target
+2.6 kernel, you must also ensure that the 'HZ' define is set to 100
+(1000 is the default) as QEMU cannot currently emulate timers at
+frequencies greater than 100 Hz on host Linux systems < 2.6. In
+@file{include/asm/param.h}, replace:
+
+@example
+# define HZ 1000 /* Internal kernel timer frequency */
+@end example
+by
+@example
+# define HZ 100 /* Internal kernel timer frequency */
+@end example
+
+@end enumerate
+
+The file config-2.x.x gives the configuration of the example kernels.
+
+Just type
+@example
+make bzImage
+@end example
+
+As you would do to make a real kernel. Then you can use with QEMU
+exactly the same kernel as you would boot on your PC (in
+@file{arch/i386/boot/bzImage}).
+
+@node gdb_usage
+@section GDB usage
+
+QEMU has a primitive support to work with gdb, so that you can do
+'Ctrl-C' while the virtual machine is running and inspect its state.
+
+In order to use gdb, launch qemu with the '-s' option. It will wait for a
+gdb connection:
+@example
+> qemu -s -kernel arch/i386/boot/bzImage -hda root-2.4.20.img -append "root=/dev/hda"
+Connected to host network interface: tun0
+Waiting gdb connection on port 1234
+@end example
+
+Then launch gdb on the 'vmlinux' executable:
+@example
+> gdb vmlinux
+@end example
+
+In gdb, connect to QEMU:
+@example
+(gdb) target remote localhost:1234
+@end example
+
+Then you can use gdb normally. For example, type 'c' to launch the kernel:
+@example
+(gdb) c
+@end example
+
+Here are some useful tips in order to use gdb on system code:
+
+@enumerate
+@item
+Use @code{info reg} to display all the CPU registers.
+@item
+Use @code{x/10i $eip} to display the code at the PC position.
+@item
+Use @code{set architecture i8086} to dump 16 bit code. Then use
+@code{x/10i $cs*16+*eip} to dump the code at the PC position.
+@end enumerate
+
+@section Target OS specific information
+
+@subsection Linux
+
+To have access to SVGA graphic modes under X11, use the @code{vesa} or
+the @code{cirrus} X11 driver. For optimal performances, use 16 bit
+color depth in the guest and the host OS.
+
+When using a 2.6 guest Linux kernel, you should add the option
+@code{clock=pit} on the kernel command line because the 2.6 Linux
+kernels make very strict real time clock checks by default that QEMU
+cannot simulate exactly.
+
+@subsection Windows
+
+If you have a slow host, using Windows 95 is better as it gives the
+best speed. Windows 2000 is also a good choice.
+
+@subsubsection SVGA graphic modes support
+
+QEMU emulates a Cirrus Logic GD5446 Video
+card. All Windows versions starting from Windows 95 should recognize
+and use this graphic card. For optimal performances, use 16 bit color
+depth in the guest and the host OS.
+
+@subsubsection CPU usage reduction
+
+Windows 9x does not correctly use the CPU HLT
+instruction. The result is that it takes host CPU cycles even when
+idle. You can install the utility from
+@url{http://www.user.cityline.ru/~maxamn/amnhltm.zip} to solve this
+problem. Note that no such tool is needed for NT, 2000 or XP.
+
+@subsubsection Windows 2000 disk full problems
+
+Currently (release 0.6.0) QEMU has a bug which gives a @code{disk
+full} error during installation of some releases of Windows 2000. The
+workaround is to stop QEMU as soon as you notice that your disk image
+size is growing too fast (monitor it with @code{ls -ls}). Then
+relaunch QEMU to continue the installation. If you still experience
+the problem, relaunch QEMU again.
+
+Future QEMU releases are likely to correct this bug.
+
+@subsubsection Windows XP security problems
+
+Some releases of Windows XP install correctly but give a security
+error when booting:
+@example
+A problem is preventing Windows from accurately checking the
+license for this computer. Error code: 0x800703e6.
+@end example
+The only known workaround is to boot in Safe mode
+without networking support.
+
+Future QEMU releases are likely to correct this bug.
+
+@subsection MS-DOS and FreeDOS
+
+@subsubsection CPU usage reduction
+
+DOS does not correctly use the CPU HLT instruction. The result is that
+it takes host CPU cycles even when idle. You can install the utility
+from @url{http://www.vmware.com/software/dosidle210.zip} to solve this
+problem.
+
+@chapter QEMU PowerPC System emulator invocation
+
+Use the executable @file{qemu-system-ppc} to simulate a complete PREP
+or PowerMac PowerPC system.
+
+QEMU emulates the following PowerMac peripherials:
+
+@itemize @minus
+@item
+UniNorth PCI Bridge
+@item
+PCI VGA compatible card with VESA Bochs Extensions
+@item
+2 PMAC IDE interfaces with hard disk and CD-ROM support
+@item
+NE2000 PCI adapters
+@item
+Non Volatile RAM
+@item
+VIA-CUDA with ADB keyboard and mouse.
+@end itemize
+
+QEMU emulates the following PREP peripherials:
+
+@itemize @minus
+@item
+PCI Bridge
+@item
+PCI VGA compatible card with VESA Bochs Extensions
+@item
+2 IDE interfaces with hard disk and CD-ROM support
+@item
+Floppy disk
+@item
+NE2000 network adapters
+@item
+Serial port
+@item
+PREP Non Volatile RAM
+@item
+PC compatible keyboard and mouse.
+@end itemize
+
+QEMU uses the Open Hack'Ware Open Firmware Compatible BIOS available at
+@url{http://site.voila.fr/jmayer/OpenHackWare/index.htm}.
+
+You can read the qemu PC system emulation chapter to have more
+informations about QEMU usage.
+
+@c man begin OPTIONS
+
+The following options are specific to the PowerPC emulation:
+
+@table @option
+
+@item -prep
+Simulate a PREP system (default is PowerMAC)
+
+@item -g WxH[xDEPTH]
+
+Set the initial VGA graphic mode. The default is 800x600x15.
+
+@end table
+
+@c man end
+
+
+More information is available at
+@url{http://jocelyn.mayer.free.fr/qemu-ppc/}.
+
+@chapter QEMU User space emulator invocation
+
+@section Quick Start
+
+In order to launch a Linux process, QEMU needs the process executable
+itself and all the target (x86) dynamic libraries used by it.
+
+@itemize
+
+@item On x86, you can just try to launch any process by using the native
+libraries:
+
+@example
+qemu-i386 -L / /bin/ls
+@end example
+
+@code{-L /} tells that the x86 dynamic linker must be searched with a
+@file{/} prefix.
+
+@item Since QEMU is also a linux process, you can launch qemu with qemu (NOTE: you can only do that if you compiled QEMU from the sources):
+
+@example
+qemu-i386 -L / qemu-i386 -L / /bin/ls
+@end example
+
+@item On non x86 CPUs, you need first to download at least an x86 glibc
+(@file{qemu-runtime-i386-XXX-.tar.gz} on the QEMU web page). Ensure that
+@code{LD_LIBRARY_PATH} is not set:
+
+@example
+unset LD_LIBRARY_PATH
+@end example
+
+Then you can launch the precompiled @file{ls} x86 executable:
+
+@example
+qemu-i386 tests/i386/ls
+@end example
+You can look at @file{qemu-binfmt-conf.sh} so that
+QEMU is automatically launched by the Linux kernel when you try to
+launch x86 executables. It requires the @code{binfmt_misc} module in the
+Linux kernel.
+
+@item The x86 version of QEMU is also included. You can try weird things such as:
+@example
+qemu-i386 /usr/local/qemu-i386/bin/qemu-i386 /usr/local/qemu-i386/bin/ls-i386
+@end example
+
+@end itemize
+
+@section Wine launch
+
+@itemize
+
+@item Ensure that you have a working QEMU with the x86 glibc
+distribution (see previous section). In order to verify it, you must be
+able to do:
+
+@example
+qemu-i386 /usr/local/qemu-i386/bin/ls-i386
+@end example
+
+@item Download the binary x86 Wine install
+(@file{qemu-XXX-i386-wine.tar.gz} on the QEMU web page).
+
+@item Configure Wine on your account. Look at the provided script
+@file{/usr/local/qemu-i386/bin/wine-conf.sh}. Your previous
+@code{$@{HOME@}/.wine} directory is saved to @code{$@{HOME@}/.wine.org}.
+
+@item Then you can try the example @file{putty.exe}:
+
+@example
+qemu-i386 /usr/local/qemu-i386/wine/bin/wine /usr/local/qemu-i386/wine/c/Program\ Files/putty.exe
+@end example
+
+@end itemize
+
+@section Command line options
+
+@example
+usage: qemu-i386 [-h] [-d] [-L path] [-s size] program [arguments...]
+@end example
+
+@table @option
+@item -h
+Print the help
+@item -L path
+Set the x86 elf interpreter prefix (default=/usr/local/qemu-i386)
+@item -s size
+Set the x86 stack size in bytes (default=524288)
+@end table
+
+Debug options:
+
+@table @option
+@item -d
+Activate log (logfile=/tmp/qemu.log)
+@item -p pagesize
+Act as if the host page size was 'pagesize' bytes
+@end table
+
+@node compilation
+@chapter Compilation from the sources
+
+@section Linux/BSD
+
+Read the @file{README} which gives the related information.
+
+@section Windows
+
+@itemize
+@item Install the current versions of MSYS and MinGW from
+@url{http://www.mingw.org/}. You can find detailed installation
+instructions in the download section and the FAQ.
+
+@item Download
+the MinGW development library of SDL 1.2.x
+(@file{SDL-devel-1.2.x-mingw32.tar.gz}) from
+@url{http://www.libsdl.org}. Unpack it in a temporary place, and
+unpack the archive @file{i386-mingw32msvc.tar.gz} in the MinGW tool
+directory. Edit the @file{sdl-config} script so that it gives the
+correct SDL directory when invoked.
+
+@item Extract the current version of QEMU.
+
+@item Start the MSYS shell (file @file{msys.bat}).
+
+@item Change to the QEMU directory. Launch @file{./configure} and
+@file{make}. If you have problems using SDL, verify that
+@file{sdl-config} can be launched from the MSYS command line.
+
+@item You can install QEMU in @file{Program Files/Qemu} by typing
+@file{make install}. Don't forget to copy @file{SDL.dll} in
+@file{Program Files/Qemu}.
+
+@end itemize
+
+@section Cross compilation for Windows with Linux
+
+@itemize
+@item
+Install the MinGW cross compilation tools available at
+@url{http://www.mingw.org/}.
+
+@item
+Install the Win32 version of SDL (@url{http://www.libsdl.org}) by
+unpacking @file{i386-mingw32msvc.tar.gz}. Set up the PATH environment
+variable so that @file{i386-mingw32msvc-sdl-config} can be launched by
+the QEMU configuration script.
+
+@item
+Configure QEMU for Windows cross compilation:
+@example
+./configure --enable-mingw32
+@end example
+If necessary, you can change the cross-prefix according to the prefix
+choosen for the MinGW tools with --cross-prefix. You can also use
+--prefix to set the Win32 install path.
+
+@item You can install QEMU in the installation directory by typing
+@file{make install}. Don't forget to copy @file{SDL.dll} in the
+installation directory.
+
+@end itemize
+
+Note: Currently, Wine does not seem able to launch
+QEMU for Win32.
+
+@section Mac OS X
+
+The Mac OS X patches are not fully merged in QEMU, so you should look
+at the QEMU mailing list archive to have all the necessary
+information.
+
--- /dev/null
+/*
+ * create a COW disk image
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+
+void *get_mmap_addr(unsigned long size)
+{
+ return NULL;
+}
+
+void qemu_free(void *ptr)
+{
+ free(ptr);
+}
+
+void *qemu_malloc(size_t size)
+{
+ return malloc(size);
+}
+
+void *qemu_mallocz(size_t size)
+{
+ void *ptr;
+ ptr = qemu_malloc(size);
+ if (!ptr)
+ return NULL;
+ memset(ptr, 0, size);
+ return ptr;
+}
+
+char *qemu_strdup(const char *str)
+{
+ char *ptr;
+ ptr = qemu_malloc(strlen(str) + 1);
+ if (!ptr)
+ return NULL;
+ strcpy(ptr, str);
+ return ptr;
+}
+
+void pstrcpy(char *buf, int buf_size, const char *str)
+{
+ int c;
+ char *q = buf;
+
+ if (buf_size <= 0)
+ return;
+
+ for(;;) {
+ c = *str++;
+ if (c == 0 || q >= buf + buf_size - 1)
+ break;
+ *q++ = c;
+ }
+ *q = '\0';
+}
+
+/* strcat and truncate. */
+char *pstrcat(char *buf, int buf_size, const char *s)
+{
+ int len;
+ len = strlen(buf);
+ if (len < buf_size)
+ pstrcpy(buf + len, buf_size - len, s);
+ return buf;
+}
+
+int strstart(const char *str, const char *val, const char **ptr)
+{
+ const char *p, *q;
+ p = str;
+ q = val;
+ while (*q != '\0') {
+ if (*p != *q)
+ return 0;
+ p++;
+ q++;
+ }
+ if (ptr)
+ *ptr = p;
+ return 1;
+}
+
+void term_printf(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ vprintf(fmt, ap);
+ va_end(ap);
+}
+
+void __attribute__((noreturn)) error(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ fprintf(stderr, "qemu-img: ");
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, "\n");
+ exit(1);
+ va_end(ap);
+}
+
+static void format_print(void *opaque, const char *name)
+{
+ printf(" %s", name);
+}
+
+void help(void)
+{
+ printf("qemu-img version " QEMU_VERSION ", Copyright (c) 2004 Fabrice Bellard\n"
+ "usage: qemu-img command [command options]\n"
+ "QEMU disk image utility\n"
+ "\n"
+ "Command syntax:\n"
+ " create [-e] [-b base_image] [-f fmt] filename [size]\n"
+ " commit [-f fmt] filename\n"
+ " convert [-c] [-e] [-f fmt] filename [-O output_fmt] output_filename\n"
+ " info [-f fmt] filename\n"
+ "\n"
+ "Command parameters:\n"
+ " 'filename' is a disk image filename\n"
+ " 'base_image' is the read-only disk image which is used as base for a copy on\n"
+ " write image; the copy on write image only stores the modified data\n"
+ " 'fmt' is the disk image format. It is guessed automatically in most cases\n"
+ " 'size' is the disk image size in kilobytes. Optional suffixes 'M' (megabyte)\n"
+ " and 'G' (gigabyte) are supported\n"
+ " 'output_filename' is the destination disk image filename\n"
+ " 'output_fmt' is the destination format\n"
+ " '-c' indicates that target image must be compressed (qcow format only)\n"
+ " '-e' indicates that the target image must be encrypted (qcow format only)\n"
+ );
+ printf("\nSupported format:");
+ bdrv_iterate_format(format_print, NULL);
+ printf("\n");
+ exit(1);
+}
+
+
+#define NB_SUFFIXES 4
+
+static void get_human_readable_size(char *buf, int buf_size, int64_t size)
+{
+ char suffixes[NB_SUFFIXES] = "KMGT";
+ int64_t base;
+ int i;
+
+ if (size <= 999) {
+ snprintf(buf, buf_size, "%lld", size);
+ } else {
+ base = 1024;
+ for(i = 0; i < NB_SUFFIXES; i++) {
+ if (size < (10 * base)) {
+ snprintf(buf, buf_size, "%0.1f%c",
+ (double)size / base,
+ suffixes[i]);
+ break;
+ } else if (size < (1000 * base) || i == (NB_SUFFIXES - 1)) {
+ snprintf(buf, buf_size, "%lld%c",
+ (size + (base >> 1)) / base,
+ suffixes[i]);
+ break;
+ }
+ base = base * 1024;
+ }
+ }
+}
+
+#if defined(WIN32)
+/* XXX: put correct support for win32 */
+static int read_password(char *buf, int buf_size)
+{
+ int c, i;
+ printf("Password: ");
+ fflush(stdout);
+ i = 0;
+ for(;;) {
+ c = getchar();
+ if (c == '\n')
+ break;
+ if (i < (buf_size - 1))
+ buf[i++] = c;
+ }
+ buf[i] = '\0';
+ return 0;
+}
+
+#else
+
+#include <termios.h>
+
+static struct termios oldtty;
+
+static void term_exit(void)
+{
+ tcsetattr (0, TCSANOW, &oldtty);
+}
+
+static void term_init(void)
+{
+ struct termios tty;
+
+ tcgetattr (0, &tty);
+ oldtty = tty;
+
+ tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
+ |INLCR|IGNCR|ICRNL|IXON);
+ tty.c_oflag |= OPOST;
+ tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
+ tty.c_cflag &= ~(CSIZE|PARENB);
+ tty.c_cflag |= CS8;
+ tty.c_cc[VMIN] = 1;
+ tty.c_cc[VTIME] = 0;
+
+ tcsetattr (0, TCSANOW, &tty);
+
+ atexit(term_exit);
+}
+
+int read_password(char *buf, int buf_size)
+{
+ uint8_t ch;
+ int i, ret;
+
+ printf("password: ");
+ fflush(stdout);
+ term_init();
+ i = 0;
+ for(;;) {
+ ret = read(0, &ch, 1);
+ if (ret == -1) {
+ if (errno == EAGAIN || errno == EINTR) {
+ continue;
+ } else {
+ ret = -1;
+ break;
+ }
+ } else if (ret == 0) {
+ ret = -1;
+ break;
+ } else {
+ if (ch == '\r') {
+ ret = 0;
+ break;
+ }
+ if (i < (buf_size - 1))
+ buf[i++] = ch;
+ }
+ }
+ term_exit();
+ buf[i] = '\0';
+ printf("\n");
+ return ret;
+}
+#endif
+
+static BlockDriverState *bdrv_new_open(const char *filename,
+ const char *fmt)
+{
+ BlockDriverState *bs;
+ BlockDriver *drv;
+ char password[256];
+
+ bs = bdrv_new("");
+ if (!bs)
+ error("Not enough memory");
+ if (fmt) {
+ drv = bdrv_find_format(fmt);
+ if (!drv)
+ error("Unknown file format '%s'", fmt);
+ } else {
+ drv = NULL;
+ }
+ if (bdrv_open2(bs, filename, 0, drv) < 0) {
+ error("Could not open '%s'", filename);
+ }
+ if (bdrv_is_encrypted(bs)) {
+ printf("Disk image '%s' is encrypted.\n", filename);
+ if (read_password(password, sizeof(password)) < 0)
+ error("No password given");
+ if (bdrv_set_key(bs, password) < 0)
+ error("invalid password");
+ }
+ return bs;
+}
+
+static int img_create(int argc, char **argv)
+{
+ int c, ret, encrypted;
+ const char *fmt = "raw";
+ const char *filename;
+ const char *base_filename = NULL;
+ int64_t size;
+ const char *p;
+ BlockDriver *drv;
+
+ encrypted = 0;
+ for(;;) {
+ c = getopt(argc, argv, "b:f:he");
+ if (c == -1)
+ break;
+ switch(c) {
+ case 'h':
+ help();
+ break;
+ case 'b':
+ base_filename = optarg;
+ break;
+ case 'f':
+ fmt = optarg;
+ break;
+ case 'e':
+ encrypted = 1;
+ break;
+ }
+ }
+ if (optind >= argc)
+ help();
+ filename = argv[optind++];
+ size = 0;
+ if (base_filename) {
+ BlockDriverState *bs;
+ bs = bdrv_new_open(base_filename, NULL);
+ bdrv_get_geometry(bs, &size);
+ size *= 512;
+ bdrv_delete(bs);
+ } else {
+ if (optind >= argc)
+ help();
+ p = argv[optind];
+ size = strtoul(p, (char **)&p, 0);
+ if (*p == 'M') {
+ size *= 1024 * 1024;
+ } else if (*p == 'G') {
+ size *= 1024 * 1024 * 1024;
+ } else if (*p == 'k' || *p == 'K' || *p == '\0') {
+ size *= 1024;
+ } else {
+ help();
+ }
+ }
+ drv = bdrv_find_format(fmt);
+ if (!drv)
+ error("Unknown file format '%s'", fmt);
+ printf("Formating '%s', fmt=%s",
+ filename, fmt);
+ if (encrypted)
+ printf(", encrypted");
+ if (base_filename) {
+ printf(", backing_file=%s",
+ base_filename);
+ }
+ printf(", size=%lld kB\n", size / 1024);
+ ret = bdrv_create(drv, filename, size / 512, base_filename, encrypted);
+ if (ret < 0) {
+ if (ret == -ENOTSUP) {
+ error("Formatting or formatting option not supported for file format '%s'", fmt);
+ } else {
+ error("Error while formatting");
+ }
+ }
+ return 0;
+}
+
+static int img_commit(int argc, char **argv)
+{
+ int c, ret;
+ const char *filename, *fmt;
+ BlockDriver *drv;
+ BlockDriverState *bs;
+
+ fmt = NULL;
+ for(;;) {
+ c = getopt(argc, argv, "f:h");
+ if (c == -1)
+ break;
+ switch(c) {
+ case 'h':
+ help();
+ break;
+ case 'f':
+ fmt = optarg;
+ break;
+ }
+ }
+ if (optind >= argc)
+ help();
+ filename = argv[optind++];
+
+ bs = bdrv_new("");
+ if (!bs)
+ error("Not enough memory");
+ if (fmt) {
+ drv = bdrv_find_format(fmt);
+ if (!drv)
+ error("Unknown file format '%s'", fmt);
+ } else {
+ drv = NULL;
+ }
+ if (bdrv_open2(bs, filename, 0, drv) < 0) {
+ error("Could not open '%s'", filename);
+ }
+ ret = bdrv_commit(bs);
+ switch(ret) {
+ case 0:
+ printf("Image committed.\n");
+ break;
+ case -ENOENT:
+ error("No disk inserted");
+ break;
+ case -EACCES:
+ error("Image is read-only");
+ break;
+ case -ENOTSUP:
+ error("Image is already committed");
+ break;
+ default:
+ error("Error while committing image");
+ break;
+ }
+
+ bdrv_delete(bs);
+ return 0;
+}
+
+static int is_not_zero(const uint8_t *sector, int len)
+{
+ int i;
+ len >>= 2;
+ for(i = 0;i < len; i++) {
+ if (((uint32_t *)sector)[i] != 0)
+ return 1;
+ }
+ return 0;
+}
+
+static int is_allocated_sectors(const uint8_t *buf, int n, int *pnum)
+{
+ int v, i;
+
+ if (n <= 0) {
+ *pnum = 0;
+ return 0;
+ }
+ v = is_not_zero(buf, 512);
+ for(i = 1; i < n; i++) {
+ buf += 512;
+ if (v != is_not_zero(buf, 512))
+ break;
+ }
+ *pnum = i;
+ return v;
+}
+
+#define IO_BUF_SIZE 65536
+
+static int img_convert(int argc, char **argv)
+{
+ int c, ret, n, n1, compress, cluster_size, cluster_sectors, encrypt;
+ const char *filename, *fmt, *out_fmt, *out_filename;
+ BlockDriver *drv;
+ BlockDriverState *bs, *out_bs;
+ int64_t total_sectors, nb_sectors, sector_num;
+ uint8_t buf[IO_BUF_SIZE];
+ const uint8_t *buf1;
+
+ fmt = NULL;
+ out_fmt = "raw";
+ compress = 0;
+ encrypt = 0;
+ for(;;) {
+ c = getopt(argc, argv, "f:O:hce");
+ if (c == -1)
+ break;
+ switch(c) {
+ case 'h':
+ help();
+ break;
+ case 'f':
+ fmt = optarg;
+ break;
+ case 'O':
+ out_fmt = optarg;
+ break;
+ case 'c':
+ compress = 1;
+ break;
+ case 'e':
+ encrypt = 1;
+ break;
+ }
+ }
+ if (optind >= argc)
+ help();
+ filename = argv[optind++];
+ if (optind >= argc)
+ help();
+ out_filename = argv[optind++];
+
+ bs = bdrv_new_open(filename, fmt);
+
+ drv = bdrv_find_format(out_fmt);
+ if (!drv)
+ error("Unknown file format '%s'", fmt);
+ if (compress && drv != &bdrv_qcow)
+ error("Compression not supported for this file format");
+ if (encrypt && drv != &bdrv_qcow)
+ error("Encryption not supported for this file format");
+ if (compress && encrypt)
+ error("Compression and encryption not supported at the same time");
+ bdrv_get_geometry(bs, &total_sectors);
+ ret = bdrv_create(drv, out_filename, total_sectors, NULL, encrypt);
+ if (ret < 0) {
+ if (ret == -ENOTSUP) {
+ error("Formatting not supported for file format '%s'", fmt);
+ } else {
+ error("Error while formatting '%s'", out_filename);
+ }
+ }
+
+ out_bs = bdrv_new_open(out_filename, out_fmt);
+
+ if (compress) {
+ cluster_size = qcow_get_cluster_size(out_bs);
+ if (cluster_size <= 0 || cluster_size > IO_BUF_SIZE)
+ error("invalid cluster size");
+ cluster_sectors = cluster_size >> 9;
+ sector_num = 0;
+ for(;;) {
+ nb_sectors = total_sectors - sector_num;
+ if (nb_sectors <= 0)
+ break;
+ if (nb_sectors >= cluster_sectors)
+ n = cluster_sectors;
+ else
+ n = nb_sectors;
+ if (bdrv_read(bs, sector_num, buf, n) < 0)
+ error("error while reading");
+ if (n < cluster_sectors)
+ memset(buf + n * 512, 0, cluster_size - n * 512);
+ if (is_not_zero(buf, cluster_size)) {
+ if (qcow_compress_cluster(out_bs, sector_num, buf) != 0)
+ error("error while compressing sector %lld", sector_num);
+ }
+ sector_num += n;
+ }
+ } else {
+ sector_num = 0;
+ for(;;) {
+ nb_sectors = total_sectors - sector_num;
+ if (nb_sectors <= 0)
+ break;
+ if (nb_sectors >= (IO_BUF_SIZE / 512))
+ n = (IO_BUF_SIZE / 512);
+ else
+ n = nb_sectors;
+ if (bdrv_read(bs, sector_num, buf, n) < 0)
+ error("error while reading");
+ /* NOTE: at the same time we convert, we do not write zero
+ sectors to have a chance to compress the image. Ideally, we
+ should add a specific call to have the info to go faster */
+ buf1 = buf;
+ while (n > 0) {
+ if (is_allocated_sectors(buf1, n, &n1)) {
+ if (bdrv_write(out_bs, sector_num, buf1, n1) < 0)
+ error("error while writing");
+ }
+ sector_num += n1;
+ n -= n1;
+ buf1 += n1 * 512;
+ }
+ }
+ }
+ bdrv_delete(out_bs);
+ bdrv_delete(bs);
+ return 0;
+}
+
+#ifdef _WIN32
+static int64_t get_allocated_file_size(const char *filename)
+{
+ struct _stati64 st;
+ if (_stati64(filename, &st) < 0)
+ return -1;
+ return st.st_size;
+}
+#else
+static int64_t get_allocated_file_size(const char *filename)
+{
+ struct stat st;
+ if (stat(filename, &st) < 0)
+ return -1;
+ return (int64_t)st.st_blocks * 512;
+}
+#endif
+
+static int img_info(int argc, char **argv)
+{
+ int c;
+ const char *filename, *fmt;
+ BlockDriver *drv;
+ BlockDriverState *bs;
+ char fmt_name[128], size_buf[128], dsize_buf[128];
+ int64_t total_sectors, allocated_size;
+
+ fmt = NULL;
+ for(;;) {
+ c = getopt(argc, argv, "f:h");
+ if (c == -1)
+ break;
+ switch(c) {
+ case 'h':
+ help();
+ break;
+ case 'f':
+ fmt = optarg;
+ break;
+ }
+ }
+ if (optind >= argc)
+ help();
+ filename = argv[optind++];
+
+ bs = bdrv_new("");
+ if (!bs)
+ error("Not enough memory");
+ if (fmt) {
+ drv = bdrv_find_format(fmt);
+ if (!drv)
+ error("Unknown file format '%s'", fmt);
+ } else {
+ drv = NULL;
+ }
+ if (bdrv_open2(bs, filename, 0, drv) < 0) {
+ error("Could not open '%s'", filename);
+ }
+ bdrv_get_format(bs, fmt_name, sizeof(fmt_name));
+ bdrv_get_geometry(bs, &total_sectors);
+ get_human_readable_size(size_buf, sizeof(size_buf), total_sectors * 512);
+ allocated_size = get_allocated_file_size(filename);
+ if (allocated_size < 0)
+ error("Could not get file size '%s'", filename);
+ get_human_readable_size(dsize_buf, sizeof(dsize_buf),
+ allocated_size);
+ printf("image: %s\n"
+ "file format: %s\n"
+ "virtual size: %s (%lld bytes)\n"
+ "disk size: %s\n",
+ filename, fmt_name, size_buf,
+ total_sectors * 512,
+ dsize_buf);
+ if (bdrv_is_encrypted(bs))
+ printf("encrypted: yes\n");
+ bdrv_delete(bs);
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ const char *cmd;
+
+ bdrv_init();
+ if (argc < 2)
+ help();
+ cmd = argv[1];
+ optind++;
+ if (!strcmp(cmd, "create")) {
+ img_create(argc, argv);
+ } else if (!strcmp(cmd, "commit")) {
+ img_commit(argc, argv);
+ } else if (!strcmp(cmd, "convert")) {
+ img_convert(argc, argv);
+ } else if (!strcmp(cmd, "info")) {
+ img_info(argc, argv);
+ } else {
+ help();
+ }
+ return 0;
+}
--- /dev/null
+.\" $Header: /cvsroot/qemu/qemu/qemu-mkcow.1,v 1.1 2004/03/26 22:42:54 bellard Exp $
+.\"
+.\" transcript compatibility for postscript use.
+.\"
+.\" synopsis: .P! <file.ps>
+.\"
+.de P!
+.fl
+\!!1 setgray
+.fl
+\\&.\"
+.fl
+\!!0 setgray
+.fl \" force out current output buffer
+\!!save /psv exch def currentpoint translate 0 0 moveto
+\!!/showpage{}def
+.fl \" prolog
+.sy sed -e 's/^/!/' \\$1\" bring in postscript file
+\!!psv restore
+.
+.de pF
+.ie \a\\*(f1\a\a .ds f1 \\n(.f
+.el .ie \a\\*(f2\a\a .ds f2 \\n(.f
+.el .ie \a\\*(f3\a\a .ds f3 \\n(.f
+.el .ie \a\\*(f4\a\a .ds f4 \\n(.f
+.el .tm ? font overflow
+.ft \\$1
+..
+.de fP
+.ie !\a\\*(f4\a\a \{\
+. ft \\*(f4
+. ds f4\"
+' br \}
+.el .ie !\a\\*(f3\a\a \{\
+. ft \\*(f3
+. ds f3\"
+' br \}
+.el .ie !\a\\*(f2\a\a \{\
+. ft \\*(f2
+. ds f2\"
+' br \}
+.el .ie !\a\\*(f1\a\a \{\
+. ft \\*(f1
+. ds f1\"
+' br \}
+.el .tm ? font underflow
+..
+.ds f1\"
+.ds f2\"
+.ds f3\"
+.ds f4\"
+'\" t
+.ta 8n 16n 24n 32n 40n 48n 56n 64n 72n
+.TH "QEMU" "8"
+.SH "NAME"
+qemu-mkcow \(em create a copy-on-write file for qemu
+.SH "SYNOPSIS"
+.PP
+\fBqemu-mkcow\fR [\fB-h\fP] [\fB-f \fImaster_disk_image\fR\fP] [\fIcow_image\fR] [\fB\fIcow_size\fR\fP]
+.SH "DESCRIPTION"
+.PP
+The \fBqemu-mkcow\fR command creates a
+persistent copy-on-write file for \fBqemu\fR.
+
+.PP
+\fBqemu\fR can be used in a "copy-on-write" mode,
+where changes made by \fBqemu\fR do not actually
+change the disk image file. One way is to invoke
+\fBqemu\fR with -snapshot: these changes
+are stored in a temporary file, which is discarded when
+\fBqemu\fR exits.
+
+.PP
+\fBqemu-mkcow\fR creates an explicit copy-on-write
+file where changes are to be stored: this way, changes made
+inside \fBqemu\fR will still be there next time you
+run it, although the master disk image isn't ever changed.
+
+.PP
+The usual method is to create the master image, then create a
+copy-on-write file using \fBqemu-mkcow\fR with
+\fB-f\fP. The filename of the master image is stored
+inside the generated copy-on-write file: it must not be modified
+after this is run!
+
+.PP
+If no master file is specified, the effect is that of a
+blank master of size \fIcow_size\fR.
+
+.SH "SEE ALSO"
+.PP
+qemu(1), qemu-fast(1).
+.SH "AUTHOR"
+.PP
+This manual page was written by Paul Russell prussell@debian.org for
+the \fBDebian\fP system (but may be used by others). Permission is
+granted to copy, distribute and/or modify this document under
+the terms of the GNU General Public License, Version 2 any
+later version published by the Free Software Foundation.
+
+.PP
+On Debian systems, the complete text of the GNU General Public
+License can be found in /usr/share/common-licenses/GPL.
+
+.\" created by instant / docbook-to-man, Fri 12 Mar 2004, 05:58
--- /dev/null
+<HTML>
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<!-- Created on January, 25 2005 by texi2html 1.64 -->
+<!--
+Written by: Lionel Cons <Lionel.Cons@cern.ch> (original author)
+ Karl Berry <karl@freefriends.org>
+ Olaf Bachmann <obachman@mathematik.uni-kl.de>
+ and many others.
+Maintained by: Olaf Bachmann <obachman@mathematik.uni-kl.de>
+Send bugs and suggestions to <texi2html@mathematik.uni-kl.de>
+
+-->
+<HEAD>
+<TITLE>Untitled Document: </TITLE>
+
+<META NAME="description" CONTENT="Untitled Document: ">
+<META NAME="keywords" CONTENT="Untitled Document: ">
+<META NAME="resource-type" CONTENT="document">
+<META NAME="distribution" CONTENT="global">
+<META NAME="Generator" CONTENT="texi2html 1.64">
+
+</HEAD>
+
+<BODY LANG="" BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#800080" ALINK="#FF0000">
+
+<A NAME="SEC1"></A>
+<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
+<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1"> < </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC2"> > </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[ << ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1"> Up </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[ >> ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1">Top</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_Contents">Contents</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_About"> ? </A>]</TD>
+</TR></TABLE>
+<P>
+
+<H1> 1. Introduction </H1>
+<!--docid::SEC1::-->
+<P>
+
+<HR SIZE="6">
+<A NAME="SEC2"></A>
+<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
+<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1"> < </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC3"> > </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[ << ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1"> Up </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[ >> ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1">Top</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_Contents">Contents</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_About"> ? </A>]</TD>
+</TR></TABLE>
+<H2> 1.1 Features </H2>
+<!--docid::SEC2::-->
+<P>
+
+QEMU is a FAST! processor emulator using a portable dynamic
+translator.
+</P><P>
+
+QEMU has two operating modes:
+</P><P>
+
+<UL>
+
+<LI>
+Full system emulation. In this mode, QEMU emulates a full system
+(usually a PC), including a processor and various peripherials. It can
+be used to launch an different Operating System without rebooting the
+PC or to debug system code.
+<P>
+
+<LI>
+User mode emulation (Linux host only). In this mode, QEMU can launch
+Linux processes compiled for one CPU on another CPU. It can be used to
+launch the Wine Windows API emulator (<A HREF="http://www.winehq.org">http://www.winehq.org</A>) or
+to ease cross-compilation and cross-debugging.
+<P>
+
+</UL>
+<P>
+
+As QEMU requires no host kernel driver to run, it is very safe and
+easy to use.
+</P><P>
+
+QEMU generic features:
+</P><P>
+
+<UL>
+
+<LI>User space only or full system emulation.
+<P>
+
+<LI>Using dynamic translation to native code for reasonnable speed.
+<P>
+
+<LI>Working on x86 and PowerPC hosts. Being tested on ARM, Sparc32, Alpha and S390.
+<P>
+
+<LI>Self-modifying code support.
+<P>
+
+<LI>Precise exceptions support.
+<P>
+
+<LI>The virtual CPU is a library (<CODE>libqemu</CODE>) which can be used
+in other projects (look at <TT>`qemu/tests/qruncom.c'</TT> to have an
+example of user mode <CODE>libqemu</CODE> usage).
+<P>
+
+</UL>
+<P>
+
+QEMU user mode emulation features:
+<UL>
+<LI>Generic Linux system call converter, including most ioctls.
+<P>
+
+<LI>clone() emulation using native CPU clone() to use Linux scheduler for threads.
+<P>
+
+<LI>Accurate signal handling by remapping host signals to target signals.
+</UL>
+</UL>
+
+QEMU full system emulation features:
+<UL>
+<LI>QEMU can either use a full software MMU for maximum portability or use the host system call mmap() to simulate the target MMU.
+</UL>
+
+<HR SIZE="6">
+<A NAME="SEC3"></A>
+<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
+<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC2"> < </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC4"> > </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[ << ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1"> Up </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[ >> ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1">Top</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_Contents">Contents</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_About"> ? </A>]</TD>
+</TR></TABLE>
+<H2> 1.2 x86 emulation </H2>
+<!--docid::SEC3::-->
+<P>
+
+QEMU x86 target features:
+</P><P>
+
+<UL>
+
+<LI>The virtual x86 CPU supports 16 bit and 32 bit addressing with segmentation.
+LDT/GDT and IDT are emulated. VM86 mode is also supported to run DOSEMU.
+<P>
+
+<LI>Support of host page sizes bigger than 4KB in user mode emulation.
+<P>
+
+<LI>QEMU can emulate itself on x86.
+<P>
+
+<LI>An extensive Linux x86 CPU test program is included <TT>`tests/test-i386'</TT>.
+It can be used to test other x86 virtual CPUs.
+<P>
+
+</UL>
+<P>
+
+Current QEMU limitations:
+</P><P>
+
+<UL>
+
+<LI>No SSE/MMX support (yet).
+<P>
+
+<LI>No x86-64 support.
+<P>
+
+<LI>IPC syscalls are missing.
+<P>
+
+<LI>The x86 segment limits and access rights are not tested at every
+memory access (yet). Hopefully, very few OSes seem to rely on that for
+normal use.
+<P>
+
+<LI>On non x86 host CPUs, <CODE>double</CODE>s are used instead of the non standard
+10 byte <CODE>long double</CODE>s of x86 for floating point emulation to get
+maximum performances.
+<P>
+
+</UL>
+<P>
+
+<HR SIZE="6">
+<A NAME="SEC4"></A>
+<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
+<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC3"> < </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC5"> > </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[ << ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1"> Up </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[ >> ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1">Top</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_Contents">Contents</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_About"> ? </A>]</TD>
+</TR></TABLE>
+<H2> 1.3 ARM emulation </H2>
+<!--docid::SEC4::-->
+<P>
+
+<UL>
+
+<LI>Full ARM 7 user emulation.
+<P>
+
+<LI>NWFPE FPU support included in user Linux emulation.
+<P>
+
+<LI>Can run most ARM Linux binaries.
+<P>
+
+</UL>
+<P>
+
+<HR SIZE="6">
+<A NAME="SEC5"></A>
+<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
+<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC4"> < </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC6"> > </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[ << ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1"> Up </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[ >> ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1">Top</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_Contents">Contents</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_About"> ? </A>]</TD>
+</TR></TABLE>
+<H2> 1.4 PowerPC emulation </H2>
+<!--docid::SEC5::-->
+<P>
+
+<UL>
+
+<LI>Full PowerPC 32 bit emulation, including priviledged instructions,
+FPU and MMU.
+<P>
+
+<LI>Can run most PowerPC Linux binaries.
+<P>
+
+</UL>
+<P>
+
+<HR SIZE="6">
+<A NAME="SEC6"></A>
+<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
+<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC5"> < </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC7"> > </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[ << ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1"> Up </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[ >> ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1">Top</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_Contents">Contents</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_About"> ? </A>]</TD>
+</TR></TABLE>
+<H2> 1.5 SPARC emulation </H2>
+<!--docid::SEC6::-->
+<P>
+
+<UL>
+
+<LI>SPARC V8 user support, except FPU instructions.
+<P>
+
+<LI>Can run some SPARC Linux binaries.
+<P>
+
+</UL>
+<P>
+
+<HR SIZE="6">
+<A NAME="SEC7"></A>
+<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
+<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC6"> < </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC8"> > </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[ << ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1"> Up </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[ >> ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1">Top</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_Contents">Contents</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_About"> ? </A>]</TD>
+</TR></TABLE>
+<H1> 2. QEMU Internals </H1>
+<!--docid::SEC7::-->
+<P>
+
+<HR SIZE="6">
+<A NAME="SEC8"></A>
+<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
+<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC7"> < </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC9"> > </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[ << ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1"> Up </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[ >> ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1">Top</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_Contents">Contents</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_About"> ? </A>]</TD>
+</TR></TABLE>
+<H2> 2.1 QEMU compared to other emulators </H2>
+<!--docid::SEC8::-->
+<P>
+
+Like bochs <A HREF="qemu-tech.html#BIB3">[3]</A>, QEMU emulates an x86 CPU. But QEMU is much faster than
+bochs as it uses dynamic compilation. Bochs is closely tied to x86 PC
+emulation while QEMU can emulate several processors.
+</P><P>
+
+Like Valgrind <A HREF="qemu-tech.html#BIB2">[2]</A>, QEMU does user space emulation and dynamic
+translation. Valgrind is mainly a memory debugger while QEMU has no
+support for it (QEMU could be used to detect out of bound memory
+accesses as Valgrind, but it has no support to track uninitialised data
+as Valgrind does). The Valgrind dynamic translator generates better code
+than QEMU (in particular it does register allocation) but it is closely
+tied to an x86 host and target and has no support for precise exceptions
+and system emulation.
+</P><P>
+
+EM86 <A HREF="qemu-tech.html#BIB4">[4]</A> is the closest project to user space QEMU (and QEMU still uses
+some of its code, in particular the ELF file loader). EM86 was limited
+to an alpha host and used a proprietary and slow interpreter (the
+interpreter part of the FX!32 Digital Win32 code translator <A HREF="qemu-tech.html#BIB5">[5]</A>).
+</P><P>
+
+TWIN <A HREF="qemu-tech.html#BIB6">[6]</A> is a Windows API emulator like Wine. It is less accurate than
+Wine but includes a protected mode x86 interpreter to launch x86 Windows
+executables. Such an approach has greater potential because most of the
+Windows API is executed natively but it is far more difficult to develop
+because all the data structures and function parameters exchanged
+between the API and the x86 code must be converted.
+</P><P>
+
+User mode Linux <A HREF="qemu-tech.html#BIB7">[7]</A> was the only solution before QEMU to launch a
+Linux kernel as a process while not needing any host kernel
+patches. However, user mode Linux requires heavy kernel patches while
+QEMU accepts unpatched Linux kernels. The price to pay is that QEMU is
+slower.
+</P><P>
+
+The new Plex86 <A HREF="qemu-tech.html#BIB8">[8]</A> PC virtualizer is done in the same spirit as the
+qemu-fast system emulator. It requires a patched Linux kernel to work
+(you cannot launch the same kernel on your PC), but the patches are
+really small. As it is a PC virtualizer (no emulation is done except
+for some priveledged instructions), it has the potential of being
+faster than QEMU. The downside is that a complicated (and potentially
+unsafe) host kernel patch is needed.
+</P><P>
+
+The commercial PC Virtualizers (VMWare <A HREF="qemu-tech.html#BIB9">[9]</A>, VirtualPC <A HREF="qemu-tech.html#BIB10">[10]</A>, TwoOStwo
+<A HREF="qemu-tech.html#BIB11">[11]</A>) are faster than QEMU, but they all need specific, proprietary
+and potentially unsafe host drivers. Moreover, they are unable to
+provide cycle exact simulation as an emulator can.
+</P><P>
+
+<HR SIZE="6">
+<A NAME="SEC9"></A>
+<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
+<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC8"> < </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC10"> > </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[ << ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1"> Up </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[ >> ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1">Top</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_Contents">Contents</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_About"> ? </A>]</TD>
+</TR></TABLE>
+<H2> 2.2 Portable dynamic translation </H2>
+<!--docid::SEC9::-->
+<P>
+
+QEMU is a dynamic translator. When it first encounters a piece of code,
+it converts it to the host instruction set. Usually dynamic translators
+are very complicated and highly CPU dependent. QEMU uses some tricks
+which make it relatively easily portable and simple while achieving good
+performances.
+</P><P>
+
+The basic idea is to split every x86 instruction into fewer simpler
+instructions. Each simple instruction is implemented by a piece of C
+code (see <TT>`target-i386/op.c'</TT>). Then a compile time tool
+(<TT>`dyngen'</TT>) takes the corresponding object file (<TT>`op.o'</TT>)
+to generate a dynamic code generator which concatenates the simple
+instructions to build a function (see <TT>`op.h:dyngen_code()'</TT>).
+</P><P>
+
+In essence, the process is similar to <A HREF="qemu-tech.html#BIB1">[1]</A>, but more work is done at
+compile time.
+</P><P>
+
+A key idea to get optimal performances is that constant parameters can
+be passed to the simple operations. For that purpose, dummy ELF
+relocations are generated with gcc for each constant parameter. Then,
+the tool (<TT>`dyngen'</TT>) can locate the relocations and generate the
+appriopriate C code to resolve them when building the dynamic code.
+</P><P>
+
+That way, QEMU is no more difficult to port than a dynamic linker.
+</P><P>
+
+To go even faster, GCC static register variables are used to keep the
+state of the virtual CPU.
+</P><P>
+
+<HR SIZE="6">
+<A NAME="SEC10"></A>
+<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
+<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC9"> < </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC11"> > </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[ << ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1"> Up </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[ >> ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1">Top</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_Contents">Contents</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_About"> ? </A>]</TD>
+</TR></TABLE>
+<H2> 2.3 Register allocation </H2>
+<!--docid::SEC10::-->
+<P>
+
+Since QEMU uses fixed simple instructions, no efficient register
+allocation can be done. However, because RISC CPUs have a lot of
+register, most of the virtual CPU state can be put in registers without
+doing complicated register allocation.
+</P><P>
+
+<HR SIZE="6">
+<A NAME="SEC11"></A>
+<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
+<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC10"> < </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC12"> > </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[ << ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1"> Up </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[ >> ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1">Top</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_Contents">Contents</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_About"> ? </A>]</TD>
+</TR></TABLE>
+<H2> 2.4 Condition code optimisations </H2>
+<!--docid::SEC11::-->
+<P>
+
+Good CPU condition codes emulation (<CODE>EFLAGS</CODE> register on x86) is a
+critical point to get good performances. QEMU uses lazy condition code
+evaluation: instead of computing the condition codes after each x86
+instruction, it just stores one operand (called <CODE>CC_SRC</CODE>), the
+result (called <CODE>CC_DST</CODE>) and the type of operation (called
+<CODE>CC_OP</CODE>).
+</P><P>
+
+<CODE>CC_OP</CODE> is almost never explicitely set in the generated code
+because it is known at translation time.
+</P><P>
+
+In order to increase performances, a backward pass is performed on the
+generated simple instructions (see
+<CODE>target-i386/translate.c:optimize_flags()</CODE>). When it can be proved that
+the condition codes are not needed by the next instructions, no
+condition codes are computed at all.
+</P><P>
+
+<HR SIZE="6">
+<A NAME="SEC12"></A>
+<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
+<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC11"> < </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC13"> > </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[ << ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1"> Up </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[ >> ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1">Top</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_Contents">Contents</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_About"> ? </A>]</TD>
+</TR></TABLE>
+<H2> 2.5 CPU state optimisations </H2>
+<!--docid::SEC12::-->
+<P>
+
+The x86 CPU has many internal states which change the way it evaluates
+instructions. In order to achieve a good speed, the translation phase
+considers that some state information of the virtual x86 CPU cannot
+change in it. For example, if the SS, DS and ES segments have a zero
+base, then the translator does not even generate an addition for the
+segment base.
+</P><P>
+
+[The FPU stack pointer register is not handled that way yet].
+</P><P>
+
+<HR SIZE="6">
+<A NAME="SEC13"></A>
+<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
+<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC12"> < </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC14"> > </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[ << ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1"> Up </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[ >> ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1">Top</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_Contents">Contents</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_About"> ? </A>]</TD>
+</TR></TABLE>
+<H2> 2.6 Translation cache </H2>
+<!--docid::SEC13::-->
+<P>
+
+A 16 MByte cache holds the most recently used translations. For
+simplicity, it is completely flushed when it is full. A translation unit
+contains just a single basic block (a block of x86 instructions
+terminated by a jump or by a virtual CPU state change which the
+translator cannot deduce statically).
+</P><P>
+
+<HR SIZE="6">
+<A NAME="SEC14"></A>
+<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
+<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC13"> < </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC15"> > </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[ << ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1"> Up </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[ >> ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1">Top</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_Contents">Contents</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_About"> ? </A>]</TD>
+</TR></TABLE>
+<H2> 2.7 Direct block chaining </H2>
+<!--docid::SEC14::-->
+<P>
+
+After each translated basic block is executed, QEMU uses the simulated
+Program Counter (PC) and other cpu state informations (such as the CS
+segment base value) to find the next basic block.
+</P><P>
+
+In order to accelerate the most common cases where the new simulated PC
+is known, QEMU can patch a basic block so that it jumps directly to the
+next one.
+</P><P>
+
+The most portable code uses an indirect jump. An indirect jump makes
+it easier to make the jump target modification atomic. On some host
+architectures (such as x86 or PowerPC), the <CODE>JUMP</CODE> opcode is
+directly patched so that the block chaining has no overhead.
+</P><P>
+
+<HR SIZE="6">
+<A NAME="SEC15"></A>
+<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
+<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC14"> < </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC16"> > </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[ << ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1"> Up </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[ >> ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1">Top</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_Contents">Contents</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_About"> ? </A>]</TD>
+</TR></TABLE>
+<H2> 2.8 Self-modifying code and translated code invalidation </H2>
+<!--docid::SEC15::-->
+<P>
+
+Self-modifying code is a special challenge in x86 emulation because no
+instruction cache invalidation is signaled by the application when code
+is modified.
+</P><P>
+
+When translated code is generated for a basic block, the corresponding
+host page is write protected if it is not already read-only (with the
+system call <CODE>mprotect()</CODE>). Then, if a write access is done to the
+page, Linux raises a SEGV signal. QEMU then invalidates all the
+translated code in the page and enables write accesses to the page.
+</P><P>
+
+Correct translated code invalidation is done efficiently by maintaining
+a linked list of every translated block contained in a given page. Other
+linked lists are also maintained to undo direct block chaining.
+</P><P>
+
+Although the overhead of doing <CODE>mprotect()</CODE> calls is important,
+most MSDOS programs can be emulated at reasonnable speed with QEMU and
+DOSEMU.
+</P><P>
+
+Note that QEMU also invalidates pages of translated code when it detects
+that memory mappings are modified with <CODE>mmap()</CODE> or <CODE>munmap()</CODE>.
+</P><P>
+
+When using a software MMU, the code invalidation is more efficient: if
+a given code page is invalidated too often because of write accesses,
+then a bitmap representing all the code inside the page is
+built. Every store into that page checks the bitmap to see if the code
+really needs to be invalidated. It avoids invalidating the code when
+only data is modified in the page.
+</P><P>
+
+<HR SIZE="6">
+<A NAME="SEC16"></A>
+<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
+<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC15"> < </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC17"> > </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[ << ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1"> Up </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[ >> ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1">Top</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_Contents">Contents</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_About"> ? </A>]</TD>
+</TR></TABLE>
+<H2> 2.9 Exception support </H2>
+<!--docid::SEC16::-->
+<P>
+
+longjmp() is used when an exception such as division by zero is
+encountered.
+</P><P>
+
+The host SIGSEGV and SIGBUS signal handlers are used to get invalid
+memory accesses. The exact CPU state can be retrieved because all the
+x86 registers are stored in fixed host registers. The simulated program
+counter is found by retranslating the corresponding basic block and by
+looking where the host program counter was at the exception point.
+</P><P>
+
+The virtual CPU cannot retrieve the exact <CODE>EFLAGS</CODE> register because
+in some cases it is not computed because of condition code
+optimisations. It is not a big concern because the emulated code can
+still be restarted in any cases.
+</P><P>
+
+<HR SIZE="6">
+<A NAME="SEC17"></A>
+<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
+<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC16"> < </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC18"> > </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[ << ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1"> Up </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[ >> ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1">Top</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_Contents">Contents</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_About"> ? </A>]</TD>
+</TR></TABLE>
+<H2> 2.10 MMU emulation </H2>
+<!--docid::SEC17::-->
+<P>
+
+For system emulation, QEMU uses the mmap() system call to emulate the
+target CPU MMU. It works as long the emulated OS does not use an area
+reserved by the host OS (such as the area above 0xc0000000 on x86
+Linux).
+</P><P>
+
+In order to be able to launch any OS, QEMU also supports a soft
+MMU. In that mode, the MMU virtual to physical address translation is
+done at every memory access. QEMU uses an address translation cache to
+speed up the translation.
+</P><P>
+
+In order to avoid flushing the translated code each time the MMU
+mappings change, QEMU uses a physically indexed translation cache. It
+means that each basic block is indexed with its physical address.
+</P><P>
+
+When MMU mappings change, only the chaining of the basic blocks is
+reset (i.e. a basic block can no longer jump directly to another one).
+</P><P>
+
+<HR SIZE="6">
+<A NAME="SEC18"></A>
+<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
+<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC17"> < </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC19"> > </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[ << ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1"> Up </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[ >> ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1">Top</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_Contents">Contents</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_About"> ? </A>]</TD>
+</TR></TABLE>
+<H2> 2.11 Hardware interrupts </H2>
+<!--docid::SEC18::-->
+<P>
+
+In order to be faster, QEMU does not check at every basic block if an
+hardware interrupt is pending. Instead, the user must asynchrously
+call a specific function to tell that an interrupt is pending. This
+function resets the chaining of the currently executing basic
+block. It ensures that the execution will return soon in the main loop
+of the CPU emulator. Then the main loop can test if the interrupt is
+pending and handle it.
+</P><P>
+
+<HR SIZE="6">
+<A NAME="SEC19"></A>
+<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
+<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC18"> < </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC20"> > </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[ << ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1"> Up </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[ >> ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1">Top</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_Contents">Contents</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_About"> ? </A>]</TD>
+</TR></TABLE>
+<H2> 2.12 User emulation specific details </H2>
+<!--docid::SEC19::-->
+<P>
+
+<HR SIZE="6">
+<A NAME="SEC20"></A>
+<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
+<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC19"> < </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC21"> > </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[ << ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1"> Up </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[ >> ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1">Top</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_Contents">Contents</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_About"> ? </A>]</TD>
+</TR></TABLE>
+<H3> 2.12.1 Linux system call translation </H3>
+<!--docid::SEC20::-->
+<P>
+
+QEMU includes a generic system call translator for Linux. It means that
+the parameters of the system calls can be converted to fix the
+endianness and 32/64 bit issues. The IOCTLs are converted with a generic
+type description system (see <TT>`ioctls.h'</TT> and <TT>`thunk.c'</TT>).
+</P><P>
+
+QEMU supports host CPUs which have pages bigger than 4KB. It records all
+the mappings the process does and try to emulated the <CODE>mmap()</CODE>
+system calls in cases where the host <CODE>mmap()</CODE> call would fail
+because of bad page alignment.
+</P><P>
+
+<HR SIZE="6">
+<A NAME="SEC21"></A>
+<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
+<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC20"> < </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC22"> > </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[ << ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1"> Up </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[ >> ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1">Top</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_Contents">Contents</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_About"> ? </A>]</TD>
+</TR></TABLE>
+<H3> 2.12.2 Linux signals </H3>
+<!--docid::SEC21::-->
+<P>
+
+Normal and real-time signals are queued along with their information
+(<CODE>siginfo_t</CODE>) as it is done in the Linux kernel. Then an interrupt
+request is done to the virtual CPU. When it is interrupted, one queued
+signal is handled by generating a stack frame in the virtual CPU as the
+Linux kernel does. The <CODE>sigreturn()</CODE> system call is emulated to return
+from the virtual signal handler.
+</P><P>
+
+Some signals (such as SIGALRM) directly come from the host. Other
+signals are synthetized from the virtual CPU exceptions such as SIGFPE
+when a division by zero is done (see <CODE>main.c:cpu_loop()</CODE>).
+</P><P>
+
+The blocked signal mask is still handled by the host Linux kernel so
+that most signal system calls can be redirected directly to the host
+Linux kernel. Only the <CODE>sigaction()</CODE> and <CODE>sigreturn()</CODE> system
+calls need to be fully emulated (see <TT>`signal.c'</TT>).
+</P><P>
+
+<HR SIZE="6">
+<A NAME="SEC22"></A>
+<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
+<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC21"> < </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC23"> > </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[ << ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1"> Up </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[ >> ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1">Top</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_Contents">Contents</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_About"> ? </A>]</TD>
+</TR></TABLE>
+<H3> 2.12.3 clone() system call and threads </H3>
+<!--docid::SEC22::-->
+<P>
+
+The Linux clone() system call is usually used to create a thread. QEMU
+uses the host clone() system call so that real host threads are created
+for each emulated thread. One virtual CPU instance is created for each
+thread.
+</P><P>
+
+The virtual x86 CPU atomic operations are emulated with a global lock so
+that their semantic is preserved.
+</P><P>
+
+Note that currently there are still some locking issues in QEMU. In
+particular, the translated cache flush is not protected yet against
+reentrancy.
+</P><P>
+
+<HR SIZE="6">
+<A NAME="SEC23"></A>
+<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
+<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC22"> < </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC24"> > </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[ << ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1"> Up </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[ >> ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1">Top</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_Contents">Contents</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_About"> ? </A>]</TD>
+</TR></TABLE>
+<H3> 2.12.4 Self-virtualization </H3>
+<!--docid::SEC23::-->
+<P>
+
+QEMU was conceived so that ultimately it can emulate itself. Although
+it is not very useful, it is an important test to show the power of the
+emulator.
+</P><P>
+
+Achieving self-virtualization is not easy because there may be address
+space conflicts. QEMU solves this problem by being an executable ELF
+shared object as the ld-linux.so ELF interpreter. That way, it can be
+relocated at load time.
+</P><P>
+
+<HR SIZE="6">
+<A NAME="SEC24"></A>
+<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
+<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC23"> < </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC25"> > </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[ << ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1"> Up </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[ >> ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1">Top</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_Contents">Contents</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_About"> ? </A>]</TD>
+</TR></TABLE>
+<H2> 2.13 Bibliography </H2>
+<!--docid::SEC24::-->
+<P>
+
+<DL COMPACT>
+
+<DT><A NAME="BIB1">[1]</A>
+<DD><A HREF="http://citeseer.nj.nec.com/piumarta98optimizing.html">http://citeseer.nj.nec.com/piumarta98optimizing.html</A>, Optimizing
+direct threaded code by selective inlining (1998) by Ian Piumarta, Fabio
+Riccardi.
+<P>
+
+<DT><A NAME="BIB2">[2]</A>
+<DD><A HREF="http://developer.kde.org/~sewardj/">http://developer.kde.org/~sewardj/</A>, Valgrind, an open-source
+memory debugger for x86-GNU/Linux, by Julian Seward.
+<P>
+
+<DT><A NAME="BIB3">[3]</A>
+<DD><A HREF="http://bochs.sourceforge.net/">http://bochs.sourceforge.net/</A>, the Bochs IA-32 Emulator Project,
+by Kevin Lawton et al.
+<P>
+
+<DT><A NAME="BIB4">[4]</A>
+<DD><A HREF="http://www.cs.rose-hulman.edu/~donaldlf/em86/index.html">http://www.cs.rose-hulman.edu/~donaldlf/em86/index.html</A>, the EM86
+x86 emulator on Alpha-Linux.
+<P>
+
+<DT><A NAME="BIB5">[5]</A>
+<DD><A HREF="http://www.usenix.org/publications/library/proceedings/usenix-nt97/full_papers/chernoff/chernoff.pdf">http://www.usenix.org/publications/library/proceedings/usenix-nt97/full_papers/chernoff/chernoff.pdf</A>,
+DIGITAL FX!32: Running 32-Bit x86 Applications on Alpha NT, by Anton
+Chernoff and Ray Hookway.
+<P>
+
+<DT><A NAME="BIB6">[6]</A>
+<DD><A HREF="http://www.willows.com/">http://www.willows.com/</A>, Windows API library emulation from
+Willows Software.
+<P>
+
+<DT><A NAME="BIB7">[7]</A>
+<DD><A HREF="http://user-mode-linux.sourceforge.net/">http://user-mode-linux.sourceforge.net/</A>,
+The User-mode Linux Kernel.
+<P>
+
+<DT><A NAME="BIB8">[8]</A>
+<DD><A HREF="http://www.plex86.org/">http://www.plex86.org/</A>,
+The new Plex86 project.
+<P>
+
+<DT><A NAME="BIB9">[9]</A>
+<DD><A HREF="http://www.vmware.com/">http://www.vmware.com/</A>,
+The VMWare PC virtualizer.
+<P>
+
+<DT><A NAME="BIB10">[10]</A>
+<DD><A HREF="http://www.microsoft.com/windowsxp/virtualpc/">http://www.microsoft.com/windowsxp/virtualpc/</A>,
+The VirtualPC PC virtualizer.
+<P>
+
+<DT><A NAME="BIB11">[11]</A>
+<DD><A HREF="http://www.twoostwo.org/">http://www.twoostwo.org/</A>,
+The TwoOStwo PC virtualizer.
+<P>
+
+</DL>
+<P>
+
+<HR SIZE="6">
+<A NAME="SEC25"></A>
+<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
+<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC24"> < </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC26"> > </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[ << ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1"> Up </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[ >> ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1">Top</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_Contents">Contents</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_About"> ? </A>]</TD>
+</TR></TABLE>
+<H1> 3. Regression Tests </H1>
+<!--docid::SEC25::-->
+<P>
+
+In the directory <TT>`tests/'</TT>, various interesting testing programs
+are available. There are used for regression testing.
+</P><P>
+
+<HR SIZE="6">
+<A NAME="SEC26"></A>
+<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
+<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC25"> < </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC27"> > </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[ << ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1"> Up </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[ >> ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1">Top</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_Contents">Contents</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_About"> ? </A>]</TD>
+</TR></TABLE>
+<H2> 3.1 <TT>`test-i386'</TT> </H2>
+<!--docid::SEC26::-->
+<P>
+
+This program executes most of the 16 bit and 32 bit x86 instructions and
+generates a text output. It can be compared with the output obtained with
+a real CPU or another emulator. The target <CODE>make test</CODE> runs this
+program and a <CODE>diff</CODE> on the generated output.
+</P><P>
+
+The Linux system call <CODE>modify_ldt()</CODE> is used to create x86 selectors
+to test some 16 bit addressing and 32 bit with segmentation cases.
+</P><P>
+
+The Linux system call <CODE>vm86()</CODE> is used to test vm86 emulation.
+</P><P>
+
+Various exceptions are raised to test most of the x86 user space
+exception reporting.
+</P><P>
+
+<HR SIZE="6">
+<A NAME="SEC27"></A>
+<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
+<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC26"> < </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC28"> > </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[ << ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1"> Up </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[ >> ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1">Top</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_Contents">Contents</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_About"> ? </A>]</TD>
+</TR></TABLE>
+<H2> 3.2 <TT>`linux-test'</TT> </H2>
+<!--docid::SEC27::-->
+<P>
+
+This program tests various Linux system calls. It is used to verify
+that the system call parameters are correctly converted between target
+and host CPUs.
+</P><P>
+
+<HR SIZE="6">
+<A NAME="SEC28"></A>
+<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
+<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC27"> < </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[ > ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[ << ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1"> Up </A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[ >> ]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT"> <TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1">Top</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_Contents">Contents</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_About"> ? </A>]</TD>
+</TR></TABLE>
+<H2> 3.3 <TT>`qruncom.c'</TT> </H2>
+<!--docid::SEC28::-->
+<P>
+
+Example of usage of <CODE>libqemu</CODE> to emulate a user mode i386 CPU.
+<HR SIZE="6">
+<A NAME="SEC_Contents"></A>
+<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
+<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1">Top</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_Contents">Contents</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_About"> ? </A>]</TD>
+</TR></TABLE>
+<H1>Table of Contents</H1>
+<UL>
+<A NAME="TOC1" HREF="qemu-tech.html#SEC1">1. Introduction</A>
+<BR>
+<UL>
+<A NAME="TOC2" HREF="qemu-tech.html#SEC2">1.1 Features</A>
+<BR>
+<A NAME="TOC3" HREF="qemu-tech.html#SEC3">1.2 x86 emulation</A>
+<BR>
+<A NAME="TOC4" HREF="qemu-tech.html#SEC4">1.3 ARM emulation</A>
+<BR>
+<A NAME="TOC5" HREF="qemu-tech.html#SEC5">1.4 PowerPC emulation</A>
+<BR>
+<A NAME="TOC6" HREF="qemu-tech.html#SEC6">1.5 SPARC emulation</A>
+<BR>
+</UL>
+<A NAME="TOC7" HREF="qemu-tech.html#SEC7">2. QEMU Internals</A>
+<BR>
+<UL>
+<A NAME="TOC8" HREF="qemu-tech.html#SEC8">2.1 QEMU compared to other emulators</A>
+<BR>
+<A NAME="TOC9" HREF="qemu-tech.html#SEC9">2.2 Portable dynamic translation</A>
+<BR>
+<A NAME="TOC10" HREF="qemu-tech.html#SEC10">2.3 Register allocation</A>
+<BR>
+<A NAME="TOC11" HREF="qemu-tech.html#SEC11">2.4 Condition code optimisations</A>
+<BR>
+<A NAME="TOC12" HREF="qemu-tech.html#SEC12">2.5 CPU state optimisations</A>
+<BR>
+<A NAME="TOC13" HREF="qemu-tech.html#SEC13">2.6 Translation cache</A>
+<BR>
+<A NAME="TOC14" HREF="qemu-tech.html#SEC14">2.7 Direct block chaining</A>
+<BR>
+<A NAME="TOC15" HREF="qemu-tech.html#SEC15">2.8 Self-modifying code and translated code invalidation</A>
+<BR>
+<A NAME="TOC16" HREF="qemu-tech.html#SEC16">2.9 Exception support</A>
+<BR>
+<A NAME="TOC17" HREF="qemu-tech.html#SEC17">2.10 MMU emulation</A>
+<BR>
+<A NAME="TOC18" HREF="qemu-tech.html#SEC18">2.11 Hardware interrupts</A>
+<BR>
+<A NAME="TOC19" HREF="qemu-tech.html#SEC19">2.12 User emulation specific details</A>
+<BR>
+<UL>
+<A NAME="TOC20" HREF="qemu-tech.html#SEC20">2.12.1 Linux system call translation</A>
+<BR>
+<A NAME="TOC21" HREF="qemu-tech.html#SEC21">2.12.2 Linux signals</A>
+<BR>
+<A NAME="TOC22" HREF="qemu-tech.html#SEC22">2.12.3 clone() system call and threads</A>
+<BR>
+<A NAME="TOC23" HREF="qemu-tech.html#SEC23">2.12.4 Self-virtualization</A>
+<BR>
+</UL>
+<A NAME="TOC24" HREF="qemu-tech.html#SEC24">2.13 Bibliography</A>
+<BR>
+</UL>
+<A NAME="TOC25" HREF="qemu-tech.html#SEC25">3. Regression Tests</A>
+<BR>
+<UL>
+<A NAME="TOC26" HREF="qemu-tech.html#SEC26">3.1 <TT>`test-i386'</TT></A>
+<BR>
+<A NAME="TOC27" HREF="qemu-tech.html#SEC27">3.2 <TT>`linux-test'</TT></A>
+<BR>
+<A NAME="TOC28" HREF="qemu-tech.html#SEC28">3.3 <TT>`qruncom.c'</TT></A>
+<BR>
+</UL>
+</UL>
+<HR SIZE=1>
+<A NAME="SEC_OVERVIEW"></A>
+<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
+<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1">Top</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_Contents">Contents</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_About"> ? </A>]</TD>
+</TR></TABLE>
+<H1>Short Table of Contents</H1>
+<BLOCKQUOTE>
+<A NAME="TOC1" HREF="qemu-tech.html#SEC1">1. Introduction</A>
+<BR>
+<A NAME="TOC7" HREF="qemu-tech.html#SEC7">2. QEMU Internals</A>
+<BR>
+<A NAME="TOC25" HREF="qemu-tech.html#SEC25">3. Regression Tests</A>
+<BR>
+
+</BLOCKQUOTE>
+<HR SIZE=1>
+<A NAME="SEC_About"></A>
+<TABLE CELLPADDING=1 CELLSPACING=1 BORDER=0>
+<TR><TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC1">Top</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_Contents">Contents</A>]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[Index]</TD>
+<TD VALIGN="MIDDLE" ALIGN="LEFT">[<A HREF="qemu-tech.html#SEC_About"> ? </A>]</TD>
+</TR></TABLE>
+<H1>About this document</H1>
+This document was generated on <I>January, 25 2005</I>
+using <A HREF="http://www.mathematik.uni-kl.de/~obachman/Texi2html
+"><I>texi2html</I></A>
+<P></P>
+The buttons in the navigation panels have the following meaning:
+<P></P>
+<table border = "1">
+<TR>
+<TH> Button </TH>
+<TH> Name </TH>
+<TH> Go to </TH>
+<TH> From 1.2.3 go to</TH>
+</TR>
+<TR>
+<TD ALIGN="CENTER">
+ [ < ] </TD>
+<TD ALIGN="CENTER">
+Back
+</TD>
+<TD>
+previous section in reading order
+</TD>
+<TD>
+1.2.2
+</TD>
+</TR>
+<TR>
+<TD ALIGN="CENTER">
+ [ > ] </TD>
+<TD ALIGN="CENTER">
+Forward
+</TD>
+<TD>
+next section in reading order
+</TD>
+<TD>
+1.2.4
+</TD>
+</TR>
+<TR>
+<TD ALIGN="CENTER">
+ [ << ] </TD>
+<TD ALIGN="CENTER">
+FastBack
+</TD>
+<TD>
+previous or up-and-previous section
+</TD>
+<TD>
+1.1
+</TD>
+</TR>
+<TR>
+<TD ALIGN="CENTER">
+ [ Up ] </TD>
+<TD ALIGN="CENTER">
+Up
+</TD>
+<TD>
+up section
+</TD>
+<TD>
+1.2
+</TD>
+</TR>
+<TR>
+<TD ALIGN="CENTER">
+ [ >> ] </TD>
+<TD ALIGN="CENTER">
+FastForward
+</TD>
+<TD>
+next or up-and-next section
+</TD>
+<TD>
+1.3
+</TD>
+</TR>
+<TR>
+<TD ALIGN="CENTER">
+ [Top] </TD>
+<TD ALIGN="CENTER">
+Top
+</TD>
+<TD>
+cover (top) of document
+</TD>
+<TD>
+
+</TD>
+</TR>
+<TR>
+<TD ALIGN="CENTER">
+ [Contents] </TD>
+<TD ALIGN="CENTER">
+Contents
+</TD>
+<TD>
+table of contents
+</TD>
+<TD>
+
+</TD>
+</TR>
+<TR>
+<TD ALIGN="CENTER">
+ [Index] </TD>
+<TD ALIGN="CENTER">
+Index
+</TD>
+<TD>
+concept index
+</TD>
+<TD>
+
+</TD>
+</TR>
+<TR>
+<TD ALIGN="CENTER">
+ [ ? ] </TD>
+<TD ALIGN="CENTER">
+About
+</TD>
+<TD>
+this page
+</TD>
+<TD>
+
+</TD>
+</TR>
+</TABLE>
+<P></P>
+where the <STRONG> Example </STRONG> assumes that the current position
+is at <STRONG> Subsubsection One-Two-Three </STRONG> of a document of
+the following structure:
+<UL>
+<LI> 1. Section One </LI>
+<UL>
+<LI>1.1 Subsection One-One</LI>
+<UL>
+<LI> ... </LI>
+</UL>
+<LI>1.2 Subsection One-Two</LI>
+<UL>
+<LI>1.2.1 Subsubsection One-Two-One
+</LI><LI>1.2.2 Subsubsection One-Two-Two
+</LI><LI>1.2.3 Subsubsection One-Two-Three <STRONG>
+<== Current Position </STRONG>
+</LI><LI>1.2.4 Subsubsection One-Two-Four
+</LI></UL>
+<LI>1.3 Subsection One-Three</LI>
+<UL>
+<LI> ... </LI>
+</UL>
+<LI>1.4 Subsection One-Four</LI>
+</UL>
+</UL>
+
+<HR SIZE=1>
+<BR>
+<FONT SIZE="-1">
+This document was generated
+on <I>January, 25 2005</I>
+using <A HREF="http://www.mathematik.uni-kl.de/~obachman/Texi2html
+"><I>texi2html</I></A>
+
+</BODY>
+</HTML>
--- /dev/null
+\input texinfo @c -*- texinfo -*-
+
+@iftex
+@settitle QEMU Internals
+@titlepage
+@sp 7
+@center @titlefont{QEMU Internals}
+@sp 3
+@end titlepage
+@end iftex
+
+@chapter Introduction
+
+@section Features
+
+QEMU is a FAST! processor emulator using a portable dynamic
+translator.
+
+QEMU has two operating modes:
+
+@itemize @minus
+
+@item
+Full system emulation. In this mode, QEMU emulates a full system
+(usually a PC), including a processor and various peripherials. It can
+be used to launch an different Operating System without rebooting the
+PC or to debug system code.
+
+@item
+User mode emulation (Linux host only). In this mode, QEMU can launch
+Linux processes compiled for one CPU on another CPU. It can be used to
+launch the Wine Windows API emulator (@url{http://www.winehq.org}) or
+to ease cross-compilation and cross-debugging.
+
+@end itemize
+
+As QEMU requires no host kernel driver to run, it is very safe and
+easy to use.
+
+QEMU generic features:
+
+@itemize
+
+@item User space only or full system emulation.
+
+@item Using dynamic translation to native code for reasonnable speed.
+
+@item Working on x86 and PowerPC hosts. Being tested on ARM, Sparc32, Alpha and S390.
+
+@item Self-modifying code support.
+
+@item Precise exceptions support.
+
+@item The virtual CPU is a library (@code{libqemu}) which can be used
+in other projects (look at @file{qemu/tests/qruncom.c} to have an
+example of user mode @code{libqemu} usage).
+
+@end itemize
+
+QEMU user mode emulation features:
+@itemize
+@item Generic Linux system call converter, including most ioctls.
+
+@item clone() emulation using native CPU clone() to use Linux scheduler for threads.
+
+@item Accurate signal handling by remapping host signals to target signals.
+@end itemize
+@end itemize
+
+QEMU full system emulation features:
+@itemize
+@item QEMU can either use a full software MMU for maximum portability or use the host system call mmap() to simulate the target MMU.
+@end itemize
+
+@section x86 emulation
+
+QEMU x86 target features:
+
+@itemize
+
+@item The virtual x86 CPU supports 16 bit and 32 bit addressing with segmentation.
+LDT/GDT and IDT are emulated. VM86 mode is also supported to run DOSEMU.
+
+@item Support of host page sizes bigger than 4KB in user mode emulation.
+
+@item QEMU can emulate itself on x86.
+
+@item An extensive Linux x86 CPU test program is included @file{tests/test-i386}.
+It can be used to test other x86 virtual CPUs.
+
+@end itemize
+
+Current QEMU limitations:
+
+@itemize
+
+@item No SSE/MMX support (yet).
+
+@item No x86-64 support.
+
+@item IPC syscalls are missing.
+
+@item The x86 segment limits and access rights are not tested at every
+memory access (yet). Hopefully, very few OSes seem to rely on that for
+normal use.
+
+@item On non x86 host CPUs, @code{double}s are used instead of the non standard
+10 byte @code{long double}s of x86 for floating point emulation to get
+maximum performances.
+
+@end itemize
+
+@section ARM emulation
+
+@itemize
+
+@item Full ARM 7 user emulation.
+
+@item NWFPE FPU support included in user Linux emulation.
+
+@item Can run most ARM Linux binaries.
+
+@end itemize
+
+@section PowerPC emulation
+
+@itemize
+
+@item Full PowerPC 32 bit emulation, including priviledged instructions,
+FPU and MMU.
+
+@item Can run most PowerPC Linux binaries.
+
+@end itemize
+
+@section SPARC emulation
+
+@itemize
+
+@item SPARC V8 user support, except FPU instructions.
+
+@item Can run some SPARC Linux binaries.
+
+@end itemize
+
+@chapter QEMU Internals
+
+@section QEMU compared to other emulators
+
+Like bochs [3], QEMU emulates an x86 CPU. But QEMU is much faster than
+bochs as it uses dynamic compilation. Bochs is closely tied to x86 PC
+emulation while QEMU can emulate several processors.
+
+Like Valgrind [2], QEMU does user space emulation and dynamic
+translation. Valgrind is mainly a memory debugger while QEMU has no
+support for it (QEMU could be used to detect out of bound memory
+accesses as Valgrind, but it has no support to track uninitialised data
+as Valgrind does). The Valgrind dynamic translator generates better code
+than QEMU (in particular it does register allocation) but it is closely
+tied to an x86 host and target and has no support for precise exceptions
+and system emulation.
+
+EM86 [4] is the closest project to user space QEMU (and QEMU still uses
+some of its code, in particular the ELF file loader). EM86 was limited
+to an alpha host and used a proprietary and slow interpreter (the
+interpreter part of the FX!32 Digital Win32 code translator [5]).
+
+TWIN [6] is a Windows API emulator like Wine. It is less accurate than
+Wine but includes a protected mode x86 interpreter to launch x86 Windows
+executables. Such an approach has greater potential because most of the
+Windows API is executed natively but it is far more difficult to develop
+because all the data structures and function parameters exchanged
+between the API and the x86 code must be converted.
+
+User mode Linux [7] was the only solution before QEMU to launch a
+Linux kernel as a process while not needing any host kernel
+patches. However, user mode Linux requires heavy kernel patches while
+QEMU accepts unpatched Linux kernels. The price to pay is that QEMU is
+slower.
+
+The new Plex86 [8] PC virtualizer is done in the same spirit as the
+qemu-fast system emulator. It requires a patched Linux kernel to work
+(you cannot launch the same kernel on your PC), but the patches are
+really small. As it is a PC virtualizer (no emulation is done except
+for some priveledged instructions), it has the potential of being
+faster than QEMU. The downside is that a complicated (and potentially
+unsafe) host kernel patch is needed.
+
+The commercial PC Virtualizers (VMWare [9], VirtualPC [10], TwoOStwo
+[11]) are faster than QEMU, but they all need specific, proprietary
+and potentially unsafe host drivers. Moreover, they are unable to
+provide cycle exact simulation as an emulator can.
+
+@section Portable dynamic translation
+
+QEMU is a dynamic translator. When it first encounters a piece of code,
+it converts it to the host instruction set. Usually dynamic translators
+are very complicated and highly CPU dependent. QEMU uses some tricks
+which make it relatively easily portable and simple while achieving good
+performances.
+
+The basic idea is to split every x86 instruction into fewer simpler
+instructions. Each simple instruction is implemented by a piece of C
+code (see @file{target-i386/op.c}). Then a compile time tool
+(@file{dyngen}) takes the corresponding object file (@file{op.o})
+to generate a dynamic code generator which concatenates the simple
+instructions to build a function (see @file{op.h:dyngen_code()}).
+
+In essence, the process is similar to [1], but more work is done at
+compile time.
+
+A key idea to get optimal performances is that constant parameters can
+be passed to the simple operations. For that purpose, dummy ELF
+relocations are generated with gcc for each constant parameter. Then,
+the tool (@file{dyngen}) can locate the relocations and generate the
+appriopriate C code to resolve them when building the dynamic code.
+
+That way, QEMU is no more difficult to port than a dynamic linker.
+
+To go even faster, GCC static register variables are used to keep the
+state of the virtual CPU.
+
+@section Register allocation
+
+Since QEMU uses fixed simple instructions, no efficient register
+allocation can be done. However, because RISC CPUs have a lot of
+register, most of the virtual CPU state can be put in registers without
+doing complicated register allocation.
+
+@section Condition code optimisations
+
+Good CPU condition codes emulation (@code{EFLAGS} register on x86) is a
+critical point to get good performances. QEMU uses lazy condition code
+evaluation: instead of computing the condition codes after each x86
+instruction, it just stores one operand (called @code{CC_SRC}), the
+result (called @code{CC_DST}) and the type of operation (called
+@code{CC_OP}).
+
+@code{CC_OP} is almost never explicitely set in the generated code
+because it is known at translation time.
+
+In order to increase performances, a backward pass is performed on the
+generated simple instructions (see
+@code{target-i386/translate.c:optimize_flags()}). When it can be proved that
+the condition codes are not needed by the next instructions, no
+condition codes are computed at all.
+
+@section CPU state optimisations
+
+The x86 CPU has many internal states which change the way it evaluates
+instructions. In order to achieve a good speed, the translation phase
+considers that some state information of the virtual x86 CPU cannot
+change in it. For example, if the SS, DS and ES segments have a zero
+base, then the translator does not even generate an addition for the
+segment base.
+
+[The FPU stack pointer register is not handled that way yet].
+
+@section Translation cache
+
+A 16 MByte cache holds the most recently used translations. For
+simplicity, it is completely flushed when it is full. A translation unit
+contains just a single basic block (a block of x86 instructions
+terminated by a jump or by a virtual CPU state change which the
+translator cannot deduce statically).
+
+@section Direct block chaining
+
+After each translated basic block is executed, QEMU uses the simulated
+Program Counter (PC) and other cpu state informations (such as the CS
+segment base value) to find the next basic block.
+
+In order to accelerate the most common cases where the new simulated PC
+is known, QEMU can patch a basic block so that it jumps directly to the
+next one.
+
+The most portable code uses an indirect jump. An indirect jump makes
+it easier to make the jump target modification atomic. On some host
+architectures (such as x86 or PowerPC), the @code{JUMP} opcode is
+directly patched so that the block chaining has no overhead.
+
+@section Self-modifying code and translated code invalidation
+
+Self-modifying code is a special challenge in x86 emulation because no
+instruction cache invalidation is signaled by the application when code
+is modified.
+
+When translated code is generated for a basic block, the corresponding
+host page is write protected if it is not already read-only (with the
+system call @code{mprotect()}). Then, if a write access is done to the
+page, Linux raises a SEGV signal. QEMU then invalidates all the
+translated code in the page and enables write accesses to the page.
+
+Correct translated code invalidation is done efficiently by maintaining
+a linked list of every translated block contained in a given page. Other
+linked lists are also maintained to undo direct block chaining.
+
+Although the overhead of doing @code{mprotect()} calls is important,
+most MSDOS programs can be emulated at reasonnable speed with QEMU and
+DOSEMU.
+
+Note that QEMU also invalidates pages of translated code when it detects
+that memory mappings are modified with @code{mmap()} or @code{munmap()}.
+
+When using a software MMU, the code invalidation is more efficient: if
+a given code page is invalidated too often because of write accesses,
+then a bitmap representing all the code inside the page is
+built. Every store into that page checks the bitmap to see if the code
+really needs to be invalidated. It avoids invalidating the code when
+only data is modified in the page.
+
+@section Exception support
+
+longjmp() is used when an exception such as division by zero is
+encountered.
+
+The host SIGSEGV and SIGBUS signal handlers are used to get invalid
+memory accesses. The exact CPU state can be retrieved because all the
+x86 registers are stored in fixed host registers. The simulated program
+counter is found by retranslating the corresponding basic block and by
+looking where the host program counter was at the exception point.
+
+The virtual CPU cannot retrieve the exact @code{EFLAGS} register because
+in some cases it is not computed because of condition code
+optimisations. It is not a big concern because the emulated code can
+still be restarted in any cases.
+
+@section MMU emulation
+
+For system emulation, QEMU uses the mmap() system call to emulate the
+target CPU MMU. It works as long the emulated OS does not use an area
+reserved by the host OS (such as the area above 0xc0000000 on x86
+Linux).
+
+In order to be able to launch any OS, QEMU also supports a soft
+MMU. In that mode, the MMU virtual to physical address translation is
+done at every memory access. QEMU uses an address translation cache to
+speed up the translation.
+
+In order to avoid flushing the translated code each time the MMU
+mappings change, QEMU uses a physically indexed translation cache. It
+means that each basic block is indexed with its physical address.
+
+When MMU mappings change, only the chaining of the basic blocks is
+reset (i.e. a basic block can no longer jump directly to another one).
+
+@section Hardware interrupts
+
+In order to be faster, QEMU does not check at every basic block if an
+hardware interrupt is pending. Instead, the user must asynchrously
+call a specific function to tell that an interrupt is pending. This
+function resets the chaining of the currently executing basic
+block. It ensures that the execution will return soon in the main loop
+of the CPU emulator. Then the main loop can test if the interrupt is
+pending and handle it.
+
+@section User emulation specific details
+
+@subsection Linux system call translation
+
+QEMU includes a generic system call translator for Linux. It means that
+the parameters of the system calls can be converted to fix the
+endianness and 32/64 bit issues. The IOCTLs are converted with a generic
+type description system (see @file{ioctls.h} and @file{thunk.c}).
+
+QEMU supports host CPUs which have pages bigger than 4KB. It records all
+the mappings the process does and try to emulated the @code{mmap()}
+system calls in cases where the host @code{mmap()} call would fail
+because of bad page alignment.
+
+@subsection Linux signals
+
+Normal and real-time signals are queued along with their information
+(@code{siginfo_t}) as it is done in the Linux kernel. Then an interrupt
+request is done to the virtual CPU. When it is interrupted, one queued
+signal is handled by generating a stack frame in the virtual CPU as the
+Linux kernel does. The @code{sigreturn()} system call is emulated to return
+from the virtual signal handler.
+
+Some signals (such as SIGALRM) directly come from the host. Other
+signals are synthetized from the virtual CPU exceptions such as SIGFPE
+when a division by zero is done (see @code{main.c:cpu_loop()}).
+
+The blocked signal mask is still handled by the host Linux kernel so
+that most signal system calls can be redirected directly to the host
+Linux kernel. Only the @code{sigaction()} and @code{sigreturn()} system
+calls need to be fully emulated (see @file{signal.c}).
+
+@subsection clone() system call and threads
+
+The Linux clone() system call is usually used to create a thread. QEMU
+uses the host clone() system call so that real host threads are created
+for each emulated thread. One virtual CPU instance is created for each
+thread.
+
+The virtual x86 CPU atomic operations are emulated with a global lock so
+that their semantic is preserved.
+
+Note that currently there are still some locking issues in QEMU. In
+particular, the translated cache flush is not protected yet against
+reentrancy.
+
+@subsection Self-virtualization
+
+QEMU was conceived so that ultimately it can emulate itself. Although
+it is not very useful, it is an important test to show the power of the
+emulator.
+
+Achieving self-virtualization is not easy because there may be address
+space conflicts. QEMU solves this problem by being an executable ELF
+shared object as the ld-linux.so ELF interpreter. That way, it can be
+relocated at load time.
+
+@section Bibliography
+
+@table @asis
+
+@item [1]
+@url{http://citeseer.nj.nec.com/piumarta98optimizing.html}, Optimizing
+direct threaded code by selective inlining (1998) by Ian Piumarta, Fabio
+Riccardi.
+
+@item [2]
+@url{http://developer.kde.org/~sewardj/}, Valgrind, an open-source
+memory debugger for x86-GNU/Linux, by Julian Seward.
+
+@item [3]
+@url{http://bochs.sourceforge.net/}, the Bochs IA-32 Emulator Project,
+by Kevin Lawton et al.
+
+@item [4]
+@url{http://www.cs.rose-hulman.edu/~donaldlf/em86/index.html}, the EM86
+x86 emulator on Alpha-Linux.
+
+@item [5]
+@url{http://www.usenix.org/publications/library/proceedings/usenix-nt97/full_papers/chernoff/chernoff.pdf},
+DIGITAL FX!32: Running 32-Bit x86 Applications on Alpha NT, by Anton
+Chernoff and Ray Hookway.
+
+@item [6]
+@url{http://www.willows.com/}, Windows API library emulation from
+Willows Software.
+
+@item [7]
+@url{http://user-mode-linux.sourceforge.net/},
+The User-mode Linux Kernel.
+
+@item [8]
+@url{http://www.plex86.org/},
+The new Plex86 project.
+
+@item [9]
+@url{http://www.vmware.com/},
+The VMWare PC virtualizer.
+
+@item [10]
+@url{http://www.microsoft.com/windowsxp/virtualpc/},
+The VirtualPC PC virtualizer.
+
+@item [11]
+@url{http://www.twoostwo.org/},
+The TwoOStwo PC virtualizer.
+
+@end table
+
+@chapter Regression Tests
+
+In the directory @file{tests/}, various interesting testing programs
+are available. There are used for regression testing.
+
+@section @file{test-i386}
+
+This program executes most of the 16 bit and 32 bit x86 instructions and
+generates a text output. It can be compared with the output obtained with
+a real CPU or another emulator. The target @code{make test} runs this
+program and a @code{diff} on the generated output.
+
+The Linux system call @code{modify_ldt()} is used to create x86 selectors
+to test some 16 bit addressing and 32 bit with segmentation cases.
+
+The Linux system call @code{vm86()} is used to test vm86 emulation.
+
+Various exceptions are raised to test most of the x86 user space
+exception reporting.
+
+@section @file{linux-test}
+
+This program tests various Linux system calls. It is used to verify
+that the system call parameters are correctly converted between target
+and host CPUs.
+
+@section @file{qruncom.c}
+
+Example of usage of @code{libqemu} to emulate a user mode i386 CPU.
--- /dev/null
+.\" Automatically generated by Pod::Man v1.37, Pod::Parser v1.14
+.\"
+.\" Standard preamble:
+.\" ========================================================================
+.de Sh \" Subsection heading
+.br
+.if t .Sp
+.ne 5
+.PP
+\fB\\$1\fR
+.PP
+..
+.de Sp \" Vertical space (when we can't use .PP)
+.if t .sp .5v
+.if n .sp
+..
+.de Vb \" Begin verbatim text
+.ft CW
+.nf
+.ne \\$1
+..
+.de Ve \" End verbatim text
+.ft R
+.fi
+..
+.\" Set up some character translations and predefined strings. \*(-- will
+.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left
+.\" double quote, and \*(R" will give a right double quote. | will give a
+.\" real vertical bar. \*(C+ will give a nicer C++. Capital omega is used to
+.\" do unbreakable dashes and therefore won't be available. \*(C` and \*(C'
+.\" expand to `' in nroff, nothing in troff, for use with C<>.
+.tr \(*W-|\(bv\*(Tr
+.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p'
+.ie n \{\
+. ds -- \(*W-
+. ds PI pi
+. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch
+. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch
+. ds L" ""
+. ds R" ""
+. ds C` ""
+. ds C' ""
+'br\}
+.el\{\
+. ds -- \|\(em\|
+. ds PI \(*p
+. ds L" ``
+. ds R" ''
+'br\}
+.\"
+.\" If the F register is turned on, we'll generate index entries on stderr for
+.\" titles (.TH), headers (.SH), subsections (.Sh), items (.Ip), and index
+.\" entries marked with X<> in POD. Of course, you'll have to process the
+.\" output yourself in some meaningful fashion.
+.if \nF \{\
+. de IX
+. tm Index:\\$1\t\\n%\t"\\$2"
+..
+. nr % 0
+. rr F
+.\}
+.\"
+.\" For nroff, turn off justification. Always turn off hyphenation; it makes
+.\" way too many mistakes in technical documents.
+.hy 0
+.if n .na
+.\"
+.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2).
+.\" Fear. Run. Save yourself. No user-serviceable parts.
+. \" fudge factors for nroff and troff
+.if n \{\
+. ds #H 0
+. ds #V .8m
+. ds #F .3m
+. ds #[ \f1
+. ds #] \fP
+.\}
+.if t \{\
+. ds #H ((1u-(\\\\n(.fu%2u))*.13m)
+. ds #V .6m
+. ds #F 0
+. ds #[ \&
+. ds #] \&
+.\}
+. \" simple accents for nroff and troff
+.if n \{\
+. ds ' \&
+. ds ` \&
+. ds ^ \&
+. ds , \&
+. ds ~ ~
+. ds /
+.\}
+.if t \{\
+. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u"
+. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u'
+. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u'
+. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u'
+. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u'
+. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u'
+.\}
+. \" troff and (daisy-wheel) nroff accents
+.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V'
+.ds 8 \h'\*(#H'\(*b\h'-\*(#H'
+.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#]
+.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H'
+.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u'
+.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#]
+.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#]
+.ds ae a\h'-(\w'a'u*4/10)'e
+.ds Ae A\h'-(\w'A'u*4/10)'E
+. \" corrections for vroff
+.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u'
+.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u'
+. \" for low resolution devices (crt and lpr)
+.if \n(.H>23 .if \n(.V>19 \
+\{\
+. ds : e
+. ds 8 ss
+. ds o a
+. ds d- d\h'-1'\(ga
+. ds D- D\h'-1'\(hy
+. ds th \o'bp'
+. ds Th \o'LP'
+. ds ae ae
+. ds Ae AE
+.\}
+.rm #[ #] #H #V #F C
+.\" ========================================================================
+.\"
+.IX Title "QEMU 1"
+.TH QEMU 1 "2005-05-19" " " " "
+.SH "NAME"
+qemu \- QEMU System Emulator
+.SH "SYNOPSIS"
+.IX Header "SYNOPSIS"
+usage: qemu [options] [disk_image]
+.SH "DESCRIPTION"
+.IX Header "DESCRIPTION"
+The \s-1QEMU\s0 System emulator simulates a complete \s-1PC\s0.
+.PP
+In order to meet specific user needs, two versions of \s-1QEMU\s0 are
+available:
+.IP "1." 4
+\&\f(CW\*(C`qemu\-fast\*(C'\fR uses the host Memory Management Unit (\s-1MMU\s0) to
+simulate the x86 \s-1MMU\s0. It is \fIfast\fR but has limitations because
+the whole 4 \s-1GB\s0 address space cannot be used and some memory mapped
+peripherials cannot be emulated accurately yet. Therefore, a specific
+guest Linux kernel can be used
+.Sp
+Moreover there is no separation between the host and target address
+spaces, so it offers no security (the target \s-1OS\s0 can modify the
+\&\f(CW\*(C`qemu\-fast\*(C'\fR code by writing at the right addresses).
+.IP "2." 4
+\&\f(CW\*(C`qemu\*(C'\fR uses a software \s-1MMU\s0. It is about \fItwo times slower\fR
+but gives a more accurate emulation and a complete separation between
+the host and target address spaces.
+.PP
+\&\s-1QEMU\s0 emulates the following \s-1PC\s0 peripherials:
+.IP "\-" 4
+i440FX host \s-1PCI\s0 bridge and \s-1PIIX3\s0 \s-1PCI\s0 to \s-1ISA\s0 bridge
+.IP "\-" 4
+Cirrus \s-1CLGD\s0 5446 \s-1PCI\s0 \s-1VGA\s0 card or dummy \s-1VGA\s0 card with Bochs \s-1VESA\s0
+extensions (hardware level, including all non standard modes).
+.IP "\-" 4
+\&\s-1PS/2\s0 mouse and keyboard
+.IP "\-" 4
+2 \s-1PCI\s0 \s-1IDE\s0 interfaces with hard disk and CD-ROM support
+.IP "\-" 4
+Floppy disk
+.IP "\-" 4
+\&\s-1NE2000\s0 \s-1PCI\s0 network adapters
+.IP "\-" 4
+Serial ports
+.IP "\-" 4
+Soundblaster 16 card
+.PP
+\&\s-1QEMU\s0 uses the \s-1PC\s0 \s-1BIOS\s0 from the Bochs project and the Plex86/Bochs \s-1LGPL\s0
+\&\s-1VGA\s0 \s-1BIOS\s0.
+.SH "OPTIONS"
+.IX Header "OPTIONS"
+\&\fIdisk_image\fR is a raw hard disk image for \s-1IDE\s0 hard disk 0.
+.PP
+General options:
+.IP "\fB\-fda file\fR" 4
+.IX Item "-fda file"
+.PD 0
+.IP "\fB\-fdb file\fR" 4
+.IX Item "-fdb file"
+.PD
+Use \fIfile\fR as floppy disk 0/1 image You can
+use the host floppy by using \fI/dev/fd0\fR as filename.
+.IP "\fB\-hda file\fR" 4
+.IX Item "-hda file"
+.PD 0
+.IP "\fB\-hdb file\fR" 4
+.IX Item "-hdb file"
+.IP "\fB\-hdc file\fR" 4
+.IX Item "-hdc file"
+.IP "\fB\-hdd file\fR" 4
+.IX Item "-hdd file"
+.PD
+Use \fIfile\fR as hard disk 0, 1, 2 or 3 image
+.IP "\fB\-cdrom file\fR" 4
+.IX Item "-cdrom file"
+Use \fIfile\fR as CD-ROM image (you cannot use \fB\-hdc\fR and and
+\&\fB\-cdrom\fR at the same time). You can use the host CD-ROM by
+using \fI/dev/cdrom\fR as filename.
+.IP "\fB\-boot [a|c|d]\fR" 4
+.IX Item "-boot [a|c|d]"
+Boot on floppy (a), hard disk (c) or CD-ROM (d). Hard disk boot is
+the default.
+.IP "\fB\-snapshot\fR" 4
+.IX Item "-snapshot"
+Write to temporary files instead of disk image files. In this case,
+the raw disk image you use is not written back. You can however force
+the write back by pressing \fBC\-a s\fR
+.IP "\fB\-m megs\fR" 4
+.IX Item "-m megs"
+Set virtual \s-1RAM\s0 size to \fImegs\fR megabytes. Default is 128 \s-1MB\s0.
+.IP "\fB\-nographic\fR" 4
+.IX Item "-nographic"
+Normally, \s-1QEMU\s0 uses \s-1SDL\s0 to display the \s-1VGA\s0 output. With this option,
+you can totally disable graphical output so that \s-1QEMU\s0 is a simple
+command line application. The emulated serial port is redirected on
+the console. Therefore, you can still use \s-1QEMU\s0 to debug a Linux kernel
+with a serial console.
+.IP "\fB\-enable\-audio\fR" 4
+.IX Item "-enable-audio"
+The \s-1SB16\s0 emulation is disabled by default as it may give problems with
+Windows. You can enable it manually with this option.
+.IP "\fB\-localtime\fR" 4
+.IX Item "-localtime"
+Set the real time clock to local time (the default is to \s-1UTC\s0
+time). This option is needed to have correct date in MS-DOS or
+Windows.
+.IP "\fB\-full\-screen\fR" 4
+.IX Item "-full-screen"
+Start in full screen.
+.PP
+Network options:
+.IP "\fB\-n script\fR" 4
+.IX Item "-n script"
+Set \s-1TUN/TAP\s0 network init script [default=/etc/qemu\-ifup]. This script
+is launched to configure the host network interface (usually tun0)
+corresponding to the virtual \s-1NE2000\s0 card.
+.IP "\fB\-macaddr addr\fR" 4
+.IX Item "-macaddr addr"
+Set the mac address of the first interface (the format is
+aa:bb:cc:dd:ee:ff in hexa). The mac address is incremented for each
+new network interface.
+.IP "\fB\-tun\-fd fd\fR" 4
+.IX Item "-tun-fd fd"
+Assumes \fIfd\fR talks to a tap/tun host network interface and use
+it. Read <\fBhttp://bellard.org/qemu/tetrinet.html\fR> to have an
+example of its use.
+.IP "\fB\-user\-net\fR" 4
+.IX Item "-user-net"
+Use the user mode network stack. This is the default if no tun/tap
+network init script is found.
+.IP "\fB\-tftp prefix\fR" 4
+.IX Item "-tftp prefix"
+When using the user mode network stack, activate a built-in \s-1TFTP\s0
+server. All filenames beginning with \fIprefix\fR can be downloaded
+from the host to the guest using a \s-1TFTP\s0 client. The \s-1TFTP\s0 client on the
+guest must be configured in binary mode (use the command \f(CW\*(C`bin\*(C'\fR of
+the Unix \s-1TFTP\s0 client). The host \s-1IP\s0 address on the guest is as usual
+10.0.2.2.
+.IP "\fB\-smb dir\fR" 4
+.IX Item "-smb dir"
+When using the user mode network stack, activate a built-in \s-1SMB\s0
+server so that Windows OSes can access to the host files in \fIdir\fR
+transparently.
+.Sp
+In the guest Windows \s-1OS\s0, the line:
+.Sp
+.Vb 1
+\& 10.0.2.4 smbserver
+.Ve
+.Sp
+must be added in the file \fIC:\eWINDOWS\eLMHOSTS\fR (for windows 9x/Me)
+or \fIC:\eWINNT\eSYSTEM32\eDRIVERS\eETC\eLMHOSTS\fR (Windows \s-1NT/2000\s0).
+.Sp
+Then \fIdir\fR can be accessed in \fI\e\esmbserver\eqemu\fR.
+.Sp
+Note that a \s-1SAMBA\s0 server must be installed on the host \s-1OS\s0 in
+\&\fI/usr/sbin/smbd\fR. \s-1QEMU\s0 was tested succesfully with smbd version
+2.2.7a from the Red Hat 9.
+.IP "\fB\-redir [tcp|udp]:host\-port:[guest\-host]:guest\-port\fR" 4
+.IX Item "-redir [tcp|udp]:host-port:[guest-host]:guest-port"
+When using the user mode network stack, redirect incoming \s-1TCP\s0 or \s-1UDP\s0
+connections to the host port \fIhost-port\fR to the guest
+\&\fIguest-host\fR on guest port \fIguest-port\fR. If \fIguest-host\fR
+is not specified, its value is 10.0.2.15 (default address given by the
+built-in \s-1DHCP\s0 server).
+.Sp
+For example, to redirect host X11 connection from screen 1 to guest
+screen 0, use the following:
+.Sp
+.Vb 4
+\& # on the host
+\& qemu -redir tcp:6001::6000 [...]
+\& # this host xterm should open in the guest X11 server
+\& xterm -display :1
+.Ve
+.Sp
+To redirect telnet connections from host port 5555 to telnet port on
+the guest, use the following:
+.Sp
+.Vb 3
+\& # on the host
+\& qemu -redir tcp:5555::23 [...]
+\& telnet localhost 5555
+.Ve
+.Sp
+Then when you use on the host \f(CW\*(C`telnet localhost 5555\*(C'\fR, you
+connect to the guest telnet server.
+.IP "\fB\-dummy\-net\fR" 4
+.IX Item "-dummy-net"
+Use the dummy network stack: no packet will be received by the network
+cards.
+.PP
+Linux boot specific. When using this options, you can use a given
+Linux kernel without installing it in the disk image. It can be useful
+for easier testing of various kernels.
+.IP "\fB\-kernel bzImage\fR" 4
+.IX Item "-kernel bzImage"
+Use \fIbzImage\fR as kernel image.
+.IP "\fB\-append cmdline\fR" 4
+.IX Item "-append cmdline"
+Use \fIcmdline\fR as kernel command line
+.IP "\fB\-initrd file\fR" 4
+.IX Item "-initrd file"
+Use \fIfile\fR as initial ram disk.
+.PP
+Debug/Expert options:
+.IP "\fB\-serial dev\fR" 4
+.IX Item "-serial dev"
+Redirect the virtual serial port to host device \fIdev\fR. Available
+devices are:
+.RS 4
+.ie n .IP """vc""" 4
+.el .IP "\f(CWvc\fR" 4
+.IX Item "vc"
+Virtual console
+.ie n .IP """pty""" 4
+.el .IP "\f(CWpty\fR" 4
+.IX Item "pty"
+[Linux only] Pseudo \s-1TTY\s0 (a new \s-1PTY\s0 is automatically allocated)
+.ie n .IP """null""" 4
+.el .IP "\f(CWnull\fR" 4
+.IX Item "null"
+void device
+.ie n .IP """stdio""" 4
+.el .IP "\f(CWstdio\fR" 4
+.IX Item "stdio"
+[Unix only] standard input/output
+.RE
+.RS 4
+.Sp
+The default device is \f(CW\*(C`vc\*(C'\fR in graphical mode and \f(CW\*(C`stdio\*(C'\fR in
+non graphical mode.
+.Sp
+This option can be used several times to simulate up to 4 serials
+ports.
+.RE
+.IP "\fB\-monitor dev\fR" 4
+.IX Item "-monitor dev"
+Redirect the monitor to host device \fIdev\fR (same devices as the
+serial port).
+The default device is \f(CW\*(C`vc\*(C'\fR in graphical mode and \f(CW\*(C`stdio\*(C'\fR in
+non graphical mode.
+.IP "\fB\-s\fR" 4
+.IX Item "-s"
+Wait gdb connection to port 1234
+.IP "\fB\-p port\fR" 4
+.IX Item "-p port"
+Change gdb connection port.
+.IP "\fB\-S\fR" 4
+.IX Item "-S"
+Do not start \s-1CPU\s0 at startup (you must type 'c' in the monitor).
+.IP "\fB\-d\fR" 4
+.IX Item "-d"
+Output log in /tmp/qemu.log
+.IP "\fB\-isa\fR" 4
+.IX Item "-isa"
+Simulate an ISA-only system (default is \s-1PCI\s0 system).
+.IP "\fB\-std\-vga\fR" 4
+.IX Item "-std-vga"
+Simulate a standard \s-1VGA\s0 card with Bochs \s-1VBE\s0 extensions (default is
+Cirrus Logic \s-1GD5446\s0 \s-1PCI\s0 \s-1VGA\s0)
+.IP "\fB\-loadvm file\fR" 4
+.IX Item "-loadvm file"
+Start right away with a saved state (\f(CW\*(C`loadvm\*(C'\fR in monitor)
+.PP
+During the graphical emulation, you can use the following keys:
+.IP "\fBCtrl-Alt-f\fR" 4
+.IX Item "Ctrl-Alt-f"
+Toggle full screen
+.IP "\fBCtrl-Alt-n\fR" 4
+.IX Item "Ctrl-Alt-n"
+Switch to virtual console 'n'. Standard console mappings are:
+.RS 4
+.IP "\fI1\fR" 4
+.IX Item "1"
+Target system display
+.IP "\fI2\fR" 4
+.IX Item "2"
+Monitor
+.IP "\fI3\fR" 4
+.IX Item "3"
+Serial port
+.RE
+.RS 4
+.RE
+.IP "\fBCtrl-Alt\fR" 4
+.IX Item "Ctrl-Alt"
+Toggle mouse and keyboard grab.
+.PP
+In the virtual consoles, you can use \fBCtrl-Up\fR, \fBCtrl-Down\fR,
+\&\fBCtrl-PageUp\fR and \fBCtrl-PageDown\fR to move in the back log.
+.PP
+During emulation, if you are using the \fB\-nographic\fR option, use
+\&\fBCtrl-a h\fR to get terminal commands:
+.IP "\fBCtrl-a h\fR" 4
+.IX Item "Ctrl-a h"
+Print this help
+.IP "\fBCtrl-a x\fR" 4
+.IX Item "Ctrl-a x"
+Exit emulatior
+.IP "\fBCtrl-a s\fR" 4
+.IX Item "Ctrl-a s"
+Save disk data back to file (if \-snapshot)
+.IP "\fBCtrl-a b\fR" 4
+.IX Item "Ctrl-a b"
+Send break (magic sysrq in Linux)
+.IP "\fBCtrl-a c\fR" 4
+.IX Item "Ctrl-a c"
+Switch between console and monitor
+.IP "\fBCtrl-a Ctrl-a\fR" 4
+.IX Item "Ctrl-a Ctrl-a"
+Send Ctrl-a
+.PP
+The following options are specific to the PowerPC emulation:
+.IP "\fB\-prep\fR" 4
+.IX Item "-prep"
+Simulate a \s-1PREP\s0 system (default is PowerMAC)
+.IP "\fB\-g WxH[xDEPTH]\fR" 4
+.IX Item "-g WxH[xDEPTH]"
+Set the initial \s-1VGA\s0 graphic mode. The default is 800x600x15.
+.SH "SEE ALSO"
+.IX Header "SEE ALSO"
+The \s-1HTML\s0 documentation of \s-1QEMU\s0 for more precise information and Linux
+user mode emulator invocation.
+.SH "AUTHOR"
+.IX Header "AUTHOR"
+Fabrice Bellard
--- /dev/null
+/*
+ * QEMU readline utility
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+
+#define TERM_CMD_BUF_SIZE 4095
+#define TERM_MAX_CMDS 64
+#define NB_COMPLETIONS_MAX 256
+
+#define IS_NORM 0
+#define IS_ESC 1
+#define IS_CSI 2
+
+#define printf do_not_use_printf
+
+static char term_cmd_buf[TERM_CMD_BUF_SIZE + 1];
+static int term_cmd_buf_index;
+static int term_cmd_buf_size;
+
+static char term_last_cmd_buf[TERM_CMD_BUF_SIZE + 1];
+static int term_last_cmd_buf_index;
+static int term_last_cmd_buf_size;
+
+static int term_esc_state;
+static int term_esc_param;
+
+static char *term_history[TERM_MAX_CMDS];
+static int term_hist_entry = -1;
+
+static int nb_completions;
+int completion_index;
+static char *completions[NB_COMPLETIONS_MAX];
+
+static ReadLineFunc *term_readline_func;
+static int term_is_password;
+static char term_prompt[256];
+static void *term_readline_opaque;
+
+static void term_show_prompt2(void)
+{
+ term_printf("%s", term_prompt);
+ term_flush();
+ term_last_cmd_buf_index = 0;
+ term_last_cmd_buf_size = 0;
+ term_esc_state = IS_NORM;
+}
+
+static void term_show_prompt(void)
+{
+ term_show_prompt2();
+ term_cmd_buf_index = 0;
+ term_cmd_buf_size = 0;
+}
+
+/* update the displayed command line */
+static void term_update(void)
+{
+ int i, delta, len;
+
+ if (term_cmd_buf_size != term_last_cmd_buf_size ||
+ memcmp(term_cmd_buf, term_last_cmd_buf, term_cmd_buf_size) != 0) {
+ for(i = 0; i < term_last_cmd_buf_index; i++) {
+ term_printf("\033[D");
+ }
+ term_cmd_buf[term_cmd_buf_size] = '\0';
+ if (term_is_password) {
+ len = strlen(term_cmd_buf);
+ for(i = 0; i < len; i++)
+ term_printf("*");
+ } else {
+ term_printf("%s", term_cmd_buf);
+ }
+ term_printf("\033[K");
+ memcpy(term_last_cmd_buf, term_cmd_buf, term_cmd_buf_size);
+ term_last_cmd_buf_size = term_cmd_buf_size;
+ term_last_cmd_buf_index = term_cmd_buf_size;
+ }
+ if (term_cmd_buf_index != term_last_cmd_buf_index) {
+ delta = term_cmd_buf_index - term_last_cmd_buf_index;
+ if (delta > 0) {
+ for(i = 0;i < delta; i++) {
+ term_printf("\033[C");
+ }
+ } else {
+ delta = -delta;
+ for(i = 0;i < delta; i++) {
+ term_printf("\033[D");
+ }
+ }
+ term_last_cmd_buf_index = term_cmd_buf_index;
+ }
+ term_flush();
+}
+
+static void term_insert_char(int ch)
+{
+ if (term_cmd_buf_index < TERM_CMD_BUF_SIZE) {
+ memmove(term_cmd_buf + term_cmd_buf_index + 1,
+ term_cmd_buf + term_cmd_buf_index,
+ term_cmd_buf_size - term_cmd_buf_index);
+ term_cmd_buf[term_cmd_buf_index] = ch;
+ term_cmd_buf_size++;
+ term_cmd_buf_index++;
+ }
+}
+
+static void term_backward_char(void)
+{
+ if (term_cmd_buf_index > 0) {
+ term_cmd_buf_index--;
+ }
+}
+
+static void term_forward_char(void)
+{
+ if (term_cmd_buf_index < term_cmd_buf_size) {
+ term_cmd_buf_index++;
+ }
+}
+
+static void term_delete_char(void)
+{
+ if (term_cmd_buf_index < term_cmd_buf_size) {
+ memmove(term_cmd_buf + term_cmd_buf_index,
+ term_cmd_buf + term_cmd_buf_index + 1,
+ term_cmd_buf_size - term_cmd_buf_index - 1);
+ term_cmd_buf_size--;
+ }
+}
+
+static void term_backspace(void)
+{
+ if (term_cmd_buf_index > 0) {
+ term_backward_char();
+ term_delete_char();
+ }
+}
+
+static void term_bol(void)
+{
+ term_cmd_buf_index = 0;
+}
+
+static void term_eol(void)
+{
+ term_cmd_buf_index = term_cmd_buf_size;
+}
+
+static void term_up_char(void)
+{
+ int idx;
+
+ if (term_hist_entry == 0)
+ return;
+ if (term_hist_entry == -1) {
+ /* Find latest entry */
+ for (idx = 0; idx < TERM_MAX_CMDS; idx++) {
+ if (term_history[idx] == NULL)
+ break;
+ }
+ term_hist_entry = idx;
+ }
+ term_hist_entry--;
+ if (term_hist_entry >= 0) {
+ pstrcpy(term_cmd_buf, sizeof(term_cmd_buf),
+ term_history[term_hist_entry]);
+ term_cmd_buf_index = term_cmd_buf_size = strlen(term_cmd_buf);
+ }
+}
+
+static void term_down_char(void)
+{
+ if (term_hist_entry == TERM_MAX_CMDS - 1 || term_hist_entry == -1)
+ return;
+ if (term_history[++term_hist_entry] != NULL) {
+ pstrcpy(term_cmd_buf, sizeof(term_cmd_buf),
+ term_history[term_hist_entry]);
+ } else {
+ term_hist_entry = -1;
+ }
+ term_cmd_buf_index = term_cmd_buf_size = strlen(term_cmd_buf);
+}
+
+static void term_hist_add(const char *cmdline)
+{
+ char *hist_entry, *new_entry;
+ int idx;
+
+ if (cmdline[0] == '\0')
+ return;
+ new_entry = NULL;
+ if (term_hist_entry != -1) {
+ /* We were editing an existing history entry: replace it */
+ hist_entry = term_history[term_hist_entry];
+ idx = term_hist_entry;
+ if (strcmp(hist_entry, cmdline) == 0) {
+ goto same_entry;
+ }
+ }
+ /* Search cmdline in history buffers */
+ for (idx = 0; idx < TERM_MAX_CMDS; idx++) {
+ hist_entry = term_history[idx];
+ if (hist_entry == NULL)
+ break;
+ if (strcmp(hist_entry, cmdline) == 0) {
+ same_entry:
+ new_entry = hist_entry;
+ /* Put this entry at the end of history */
+ memmove(&term_history[idx], &term_history[idx + 1],
+ &term_history[TERM_MAX_CMDS] - &term_history[idx + 1]);
+ term_history[TERM_MAX_CMDS - 1] = NULL;
+ for (; idx < TERM_MAX_CMDS; idx++) {
+ if (term_history[idx] == NULL)
+ break;
+ }
+ break;
+ }
+ }
+ if (idx == TERM_MAX_CMDS) {
+ /* Need to get one free slot */
+ free(term_history[0]);
+ memcpy(term_history, &term_history[1],
+ &term_history[TERM_MAX_CMDS] - &term_history[1]);
+ term_history[TERM_MAX_CMDS - 1] = NULL;
+ idx = TERM_MAX_CMDS - 1;
+ }
+ if (new_entry == NULL)
+ new_entry = strdup(cmdline);
+ term_history[idx] = new_entry;
+ term_hist_entry = -1;
+}
+
+/* completion support */
+
+void add_completion(const char *str)
+{
+ if (nb_completions < NB_COMPLETIONS_MAX) {
+ completions[nb_completions++] = qemu_strdup(str);
+ }
+}
+
+static void term_completion(void)
+{
+ int len, i, j, max_width, nb_cols;
+ char *cmdline;
+
+ nb_completions = 0;
+
+ cmdline = qemu_malloc(term_cmd_buf_index + 1);
+ if (!cmdline)
+ return;
+ memcpy(cmdline, term_cmd_buf, term_cmd_buf_index);
+ cmdline[term_cmd_buf_index] = '\0';
+ qemu_free(cmdline);
+
+ /* no completion found */
+ if (nb_completions <= 0)
+ return;
+ if (nb_completions == 1) {
+ len = strlen(completions[0]);
+ for(i = completion_index; i < len; i++) {
+ term_insert_char(completions[0][i]);
+ }
+ /* extra space for next argument. XXX: make it more generic */
+ if (len > 0 && completions[0][len - 1] != '/')
+ term_insert_char(' ');
+ } else {
+ term_printf("\n");
+ max_width = 0;
+ for(i = 0; i < nb_completions; i++) {
+ len = strlen(completions[i]);
+ if (len > max_width)
+ max_width = len;
+ }
+ max_width += 2;
+ if (max_width < 10)
+ max_width = 10;
+ else if (max_width > 80)
+ max_width = 80;
+ nb_cols = 80 / max_width;
+ j = 0;
+ for(i = 0; i < nb_completions; i++) {
+ term_printf("%-*s", max_width, completions[i]);
+ if (++j == nb_cols || i == (nb_completions - 1)) {
+ term_printf("\n");
+ j = 0;
+ }
+ }
+ term_show_prompt2();
+ }
+}
+
+/* return true if command handled */
+void readline_handle_byte(int ch)
+{
+ switch(term_esc_state) {
+ case IS_NORM:
+ switch(ch) {
+ case 1:
+ term_bol();
+ break;
+ case 4:
+ term_delete_char();
+ break;
+ case 5:
+ term_eol();
+ break;
+ case 9:
+ term_completion();
+ break;
+ case 10:
+ case 13:
+ term_cmd_buf[term_cmd_buf_size] = '\0';
+ if (!term_is_password)
+ term_hist_add(term_cmd_buf);
+ term_printf("\n");
+ /* NOTE: readline_start can be called here */
+ term_readline_func(term_readline_opaque, term_cmd_buf);
+ break;
+ case 27:
+ term_esc_state = IS_ESC;
+ break;
+ case 127:
+ case 8:
+ term_backspace();
+ break;
+ case 155:
+ term_esc_state = IS_CSI;
+ break;
+ default:
+ if (ch >= 32) {
+ term_insert_char(ch);
+ }
+ break;
+ }
+ break;
+ case IS_ESC:
+ if (ch == '[') {
+ term_esc_state = IS_CSI;
+ term_esc_param = 0;
+ } else {
+ term_esc_state = IS_NORM;
+ }
+ break;
+ case IS_CSI:
+ switch(ch) {
+ case 'A':
+ case 'F':
+ term_up_char();
+ break;
+ case 'B':
+ case 'E':
+ term_down_char();
+ break;
+ case 'D':
+ term_backward_char();
+ break;
+ case 'C':
+ term_forward_char();
+ break;
+ case '0' ... '9':
+ term_esc_param = term_esc_param * 10 + (ch - '0');
+ goto the_end;
+ case '~':
+ switch(term_esc_param) {
+ case 1:
+ term_bol();
+ break;
+ case 3:
+ term_delete_char();
+ break;
+ case 4:
+ term_eol();
+ break;
+ }
+ break;
+ default:
+ break;
+ }
+ term_esc_state = IS_NORM;
+ the_end:
+ break;
+ }
+ term_update();
+}
+
+void readline_start(const char *prompt, int is_password,
+ ReadLineFunc *readline_func, void *opaque)
+{
+ pstrcpy(term_prompt, sizeof(term_prompt), prompt);
+ term_readline_func = readline_func;
+ term_readline_opaque = opaque;
+ term_is_password = is_password;
+ term_show_prompt();
+}
+
+const char *readline_get_history(unsigned int index)
+{
+ if (index >= TERM_MAX_CMDS)
+ return NULL;
+ return term_history[index];
+}
+
+
--- /dev/null
+/*
+ * QEMU SDL display driver
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+
+#include <SDL.h>
+
+/* keyboard stuff */
+#include <SDL_keysym.h>
+#include "keysym_adapter_sdl.h"
+#include "keyboard_rdesktop.c"
+
+#ifndef _WIN32
+#include <signal.h>
+#endif
+
+#if defined(__APPLE__)
+#define CONFIG_SDL_GENERIC_KBD
+#endif
+
+static SDL_Surface *screen;
+static int gui_grab; /* if true, all keyboard/mouse events are grabbed */
+static int last_vm_running;
+static int gui_saved_grab;
+static int gui_fullscreen;
+static int gui_key_modifier_pressed;
+static int gui_keysym;
+static void* kbd_layout=0;
+static int gui_fullscreen_initial_grab;
+static int gui_grab_code = KMOD_LALT | KMOD_LCTRL;
+static uint8_t modifiers_state[256];
+
+SDL_PixelFormat* sdl_get_format() {
+ return screen->format;
+}
+
+static void sdl_update(DisplayState *ds, int x, int y, int w, int h)
+{
+ SDL_UpdateRect(screen, x, y, w, h);
+}
+
+static void sdl_resize(DisplayState *ds, int w, int h)
+{
+ int flags;
+
+ // printf("resizing to %d %d\n", w, h);
+
+ flags = SDL_HWSURFACE|SDL_ASYNCBLIT|SDL_HWACCEL;
+ flags |= SDL_RESIZABLE;
+ if (gui_fullscreen)
+ flags |= SDL_FULLSCREEN;
+ screen = SDL_SetVideoMode(w, h, 0, flags);
+ if (!screen) {
+ fprintf(stderr, "Could not open SDL display\n");
+ exit(1);
+ }
+ ds->data = screen->pixels;
+ ds->linesize = screen->pitch;
+ ds->depth = screen->format->BitsPerPixel;
+ ds->width = w;
+ ds->height = h;
+}
+
+#ifdef CONFIG_SDL_GENERIC_KBD
+
+/* XXX: use keymap tables defined in the VNC patch because the
+ following code suppose you have a US keyboard. */
+
+static const uint8_t scancodes[SDLK_LAST] = {
+ [SDLK_ESCAPE] = 0x01,
+ [SDLK_1] = 0x02,
+ [SDLK_2] = 0x03,
+ [SDLK_3] = 0x04,
+ [SDLK_4] = 0x05,
+ [SDLK_5] = 0x06,
+ [SDLK_6] = 0x07,
+ [SDLK_7] = 0x08,
+ [SDLK_8] = 0x09,
+ [SDLK_9] = 0x0a,
+ [SDLK_0] = 0x0b,
+ [SDLK_MINUS] = 0x0c,
+ [SDLK_EQUALS] = 0x0d,
+ [SDLK_BACKSPACE] = 0x0e,
+ [SDLK_TAB] = 0x0f,
+ [SDLK_q] = 0x10,
+ [SDLK_w] = 0x11,
+ [SDLK_e] = 0x12,
+ [SDLK_r] = 0x13,
+ [SDLK_t] = 0x14,
+ [SDLK_y] = 0x15,
+ [SDLK_u] = 0x16,
+ [SDLK_i] = 0x17,
+ [SDLK_o] = 0x18,
+ [SDLK_p] = 0x19,
+ [SDLK_LEFTBRACKET] = 0x1a,
+ [SDLK_RIGHTBRACKET] = 0x1b,
+ [SDLK_RETURN] = 0x1c,
+ [SDLK_LCTRL] = 0x1d,
+ [SDLK_a] = 0x1e,
+ [SDLK_s] = 0x1f,
+ [SDLK_d] = 0x20,
+ [SDLK_f] = 0x21,
+ [SDLK_g] = 0x22,
+ [SDLK_h] = 0x23,
+ [SDLK_j] = 0x24,
+ [SDLK_k] = 0x25,
+ [SDLK_l] = 0x26,
+ [SDLK_SEMICOLON] = 0x27,
+ [SDLK_QUOTE] = 0x28,
+ [SDLK_BACKQUOTE] = 0x29,
+ [SDLK_LSHIFT] = 0x2a,
+ [SDLK_BACKSLASH] = 0x2b,
+ [SDLK_z] = 0x2c,
+ [SDLK_x] = 0x2d,
+ [SDLK_c] = 0x2e,
+ [SDLK_v] = 0x2f,
+ [SDLK_b] = 0x30,
+ [SDLK_n] = 0x31,
+ [SDLK_m] = 0x32,
+ [SDLK_COMMA] = 0x33,
+ [SDLK_PERIOD] = 0x34,
+ [SDLK_SLASH] = 0x35,
+ [SDLK_KP_MULTIPLY] = 0x37,
+ [SDLK_LALT] = 0x38,
+ [SDLK_SPACE] = 0x39,
+ [SDLK_CAPSLOCK] = 0x3a,
+ [SDLK_F1] = 0x3b,
+ [SDLK_F2] = 0x3c,
+ [SDLK_F3] = 0x3d,
+ [SDLK_F4] = 0x3e,
+ [SDLK_F5] = 0x3f,
+ [SDLK_F6] = 0x40,
+ [SDLK_F7] = 0x41,
+ [SDLK_F8] = 0x42,
+ [SDLK_F9] = 0x43,
+ [SDLK_F10] = 0x44,
+ [SDLK_NUMLOCK] = 0x45,
+ [SDLK_SCROLLOCK] = 0x46,
+ [SDLK_KP7] = 0x47,
+ [SDLK_KP8] = 0x48,
+ [SDLK_KP9] = 0x49,
+ [SDLK_KP_MINUS] = 0x4a,
+ [SDLK_KP4] = 0x4b,
+ [SDLK_KP5] = 0x4c,
+ [SDLK_KP6] = 0x4d,
+ [SDLK_KP_PLUS] = 0x4e,
+ [SDLK_KP1] = 0x4f,
+ [SDLK_KP2] = 0x50,
+ [SDLK_KP3] = 0x51,
+ [SDLK_KP0] = 0x52,
+ [SDLK_KP_PERIOD] = 0x53,
+ [SDLK_PRINT] = 0x54,
+ [SDLK_LMETA] = 0x56,
+
+ [SDLK_KP_ENTER] = 0x9c,
+ [SDLK_KP_DIVIDE] = 0xb5,
+
+ [SDLK_UP] = 0xc8,
+ [SDLK_DOWN] = 0xd0,
+ [SDLK_RIGHT] = 0xcd,
+ [SDLK_LEFT] = 0xcb,
+ [SDLK_INSERT] = 0xd2,
+ [SDLK_HOME] = 0xc7,
+ [SDLK_END] = 0xcf,
+ [SDLK_PAGEUP] = 0xc9,
+ [SDLK_PAGEDOWN] = 0xd1,
+ [SDLK_DELETE] = 0xd3,
+};
+
+static uint8_t sdl_keyevent_to_keycode(const SDL_KeyboardEvent *ev)
+{
+ return scancodes[ev->keysym.sym];
+}
+
+#elif defined(_WIN32)
+
+static uint8_t sdl_keyevent_to_keycode(const SDL_KeyboardEvent *ev)
+{
+ return ev->keysym.scancode;
+}
+
+#else
+
+static const uint8_t x_keycode_to_pc_keycode[61] = {
+ 0xc7, /* 97 Home */
+ 0xc8, /* 98 Up */
+ 0xc9, /* 99 PgUp */
+ 0xcb, /* 100 Left */
+ 0x4c, /* 101 KP-5 */
+ 0xcd, /* 102 Right */
+ 0xcf, /* 103 End */
+ 0xd0, /* 104 Down */
+ 0xd1, /* 105 PgDn */
+ 0xd2, /* 106 Ins */
+ 0xd3, /* 107 Del */
+ 0x9c, /* 108 Enter */
+ 0x9d, /* 109 Ctrl-R */
+ 0x0, /* 110 Pause */
+ 0xb7, /* 111 Print */
+ 0xb5, /* 112 Divide */
+ 0xb8, /* 113 Alt-R */
+ 0xc6, /* 114 Break */
+ 0x0, /* 115 */
+ 0x0, /* 116 */
+ 0x0, /* 117 */
+ 0x0, /* 118 */
+ 0x0, /* 119 */
+ 0x70, /* 120 Hiragana_Katakana */
+ 0x0, /* 121 */
+ 0x0, /* 122 */
+ 0x73, /* 123 backslash */
+ 0x0, /* 124 */
+ 0x0, /* 125 */
+ 0x0, /* 126 */
+ 0x0, /* 127 */
+ 0x0, /* 128 */
+ 0x79, /* 129 Henkan */
+ 0x0, /* 130 */
+ 0x7b, /* 131 Muhenkan */
+ 0x0, /* 132 */
+ 0x7d, /* 133 Yen */
+ 0x0, /* 134 */
+ 0x0, /* 135 */
+ 0x47, /* 136 KP_7 */
+ 0x48, /* 137 KP_8 */
+ 0x49, /* 138 KP_9 */
+ 0x4b, /* 139 KP_4 */
+ 0x4c, /* 140 KP_5 */
+ 0x4d, /* 141 KP_6 */
+ 0x4f, /* 142 KP_1 */
+ 0x50, /* 143 KP_2 */
+ 0x51, /* 144 KP_3 */
+ 0x52, /* 145 KP_0 */
+ 0x53, /* 146 KP_. */
+ 0x47, /* 147 KP_HOME */
+ 0x48, /* 148 KP_UP */
+ 0x49, /* 149 KP_PgUp */
+ 0x4b, /* 150 KP_Left */
+ 0x4c, /* 151 KP_ */
+ 0x4d, /* 152 KP_Right */
+ 0x4f, /* 153 KP_End */
+ 0x50, /* 154 KP_Down */
+ 0x51, /* 155 KP_PgDn */
+ 0x52, /* 156 KP_Ins */
+ 0x53, /* 157 KP_Del */
+};
+
+static uint8_t sdl_keyevent_to_keycode(const SDL_KeyboardEvent *ev)
+{
+ int keycode;
+
+ keycode = ev->keysym.scancode;
+
+ if (keycode < 9) {
+ keycode = 0;
+ } else if (keycode < 97) {
+ keycode -= 8; /* just an offset */
+ } else if (keycode < 158) {
+ /* use conversion table */
+ keycode = x_keycode_to_pc_keycode[keycode - 97];
+ } else {
+ keycode = 0;
+ }
+ return keycode;
+}
+
+#endif
+
+static void reset_keys(void)
+{
+ int i;
+ for(i = 0; i < 256; i++) {
+ if (modifiers_state[i]) {
+ if (i & 0x80)
+ kbd_put_keycode(0xe0);
+ kbd_put_keycode(i | 0x80);
+ modifiers_state[i] = 0;
+ }
+ }
+}
+
+static void sdl_process_key(SDL_KeyboardEvent *ev)
+{
+ int keycode, v;
+
+ if(kbd_layout)
+ keycode=keysym2scancode(kbd_layout, ev->keysym.sym);
+ else {
+
+ if (ev->keysym.sym == SDLK_PAUSE) {
+ /* specific case */
+ v = 0;
+ if (ev->type == SDL_KEYUP)
+ v |= 0x80;
+ kbd_put_keycode(0xe1);
+ kbd_put_keycode(0x1d | v);
+ kbd_put_keycode(0x45 | v);
+ return;
+ }
+
+ /* XXX: not portable, but avoids complicated mappings */
+ keycode = sdl_keyevent_to_keycode(ev);
+
+ switch(keycode) {
+ case 0x00:
+ /* sent when leaving window: reset the modifiers state */
+ reset_keys();
+ return;
+ case 0x2a: /* Left Shift */
+ case 0x36: /* Right Shift */
+ case 0x1d: /* Left CTRL */
+ case 0x9d: /* Right CTRL */
+ case 0x38: /* Left ALT */
+ case 0xb8: /* Right ALT */
+ if (ev->type == SDL_KEYUP)
+ modifiers_state[keycode] = 0;
+ else
+ modifiers_state[keycode] = 1;
+ break;
+ case 0x45: /* num lock */
+ case 0x3a: /* caps lock */
+ /* SDL does not send the key up event, so we generate it */
+ kbd_put_keycode(keycode);
+ kbd_put_keycode(keycode | 0x80);
+ return;
+ }
+ }
+
+ /* now send the key code */
+ if (keycode & 0x80)
+ kbd_put_keycode(0xe0);
+ if (ev->type == SDL_KEYUP)
+ kbd_put_keycode(keycode | 0x80);
+ else
+ kbd_put_keycode(keycode & 0x7f);
+}
+
+static void sdl_update_caption(void)
+{
+ char buf[1024];
+ strcpy(buf, "VTXen");
+ if (!vm_running) {
+ strcat(buf, " [Stopped]");
+ }
+ if (gui_grab) {
+ strcat(buf, " - Press Ctrl-Alt to exit grab");
+ }
+ SDL_WM_SetCaption(buf, "VTXen");
+}
+
+static void sdl_grab_start(void)
+{
+ SDL_ShowCursor(0);
+ SDL_WM_GrabInput(SDL_GRAB_ON);
+ /* dummy read to avoid moving the mouse */
+ SDL_GetRelativeMouseState(NULL, NULL);
+ gui_grab = 1;
+ sdl_update_caption();
+}
+
+static void sdl_grab_end(void)
+{
+ SDL_WM_GrabInput(SDL_GRAB_OFF);
+ SDL_ShowCursor(1);
+ gui_grab = 0;
+ sdl_update_caption();
+}
+
+static void sdl_send_mouse_event(void)
+{
+ int dx, dy, dz, state, buttons;
+ state = SDL_GetRelativeMouseState(&dx, &dy);
+ buttons = 0;
+ if (state & SDL_BUTTON(SDL_BUTTON_LEFT))
+ buttons |= MOUSE_EVENT_LBUTTON;
+ if (state & SDL_BUTTON(SDL_BUTTON_RIGHT))
+ buttons |= MOUSE_EVENT_RBUTTON;
+ if (state & SDL_BUTTON(SDL_BUTTON_MIDDLE))
+ buttons |= MOUSE_EVENT_MBUTTON;
+ /* XXX: test wheel */
+ dz = 0;
+#ifdef SDL_BUTTON_WHEELUP
+ if (state & SDL_BUTTON(SDL_BUTTON_WHEELUP))
+ dz--;
+ if (state & SDL_BUTTON(SDL_BUTTON_WHEELDOWN))
+ dz++;
+#endif
+ kbd_mouse_event(dx, dy, dz, buttons);
+}
+
+static void toggle_full_screen(DisplayState *ds)
+{
+ gui_fullscreen = !gui_fullscreen;
+ sdl_resize(ds, screen->w, screen->h);
+ if (gui_fullscreen) {
+ gui_saved_grab = gui_grab;
+ sdl_grab_start();
+ } else {
+ if (!gui_saved_grab)
+ sdl_grab_end();
+ }
+ vga_invalidate_display();
+ vga_update_display();
+}
+
+static void sdl_refresh(DisplayState *ds)
+{
+ SDL_Event ev1, *ev = &ev1;
+ int mod_state;
+
+ if (last_vm_running != vm_running) {
+ last_vm_running = vm_running;
+ sdl_update_caption();
+ }
+
+ if (is_active_console(vga_console))
+ vga_update_display();
+
+ while (SDL_PollEvent(ev)) {
+ switch (ev->type) {
+ case SDL_VIDEOEXPOSE:
+ sdl_update(ds, 0, 0, screen->w, screen->h);
+ break;
+ case SDL_KEYDOWN:
+ case SDL_KEYUP:
+ if (ev->type == SDL_KEYDOWN) {
+ mod_state = (SDL_GetModState() & gui_grab_code) ==
+ gui_grab_code;
+ gui_key_modifier_pressed = mod_state;
+ if (gui_key_modifier_pressed) {
+ int keycode;
+ keycode = sdl_keyevent_to_keycode(&ev->key);
+ switch(keycode) {
+ case 0x21: /* 'f' key on US keyboard */
+ toggle_full_screen(ds);
+ gui_keysym = 1;
+ break;
+ case 0x02 ... 0x0a: /* '1' to '9' keys */
+ console_select(keycode - 0x02);
+ if (is_active_console(vga_console)) {
+ /* tell the vga console to redisplay itself */
+ vga_invalidate_display();
+ } else {
+ /* display grab if going to a text console */
+ if (gui_grab)
+ sdl_grab_end();
+ }
+ gui_keysym = 1;
+ break;
+ default:
+ break;
+ }
+ } else if (!is_active_console(vga_console)) {
+ int keysym;
+ keysym = 0;
+ if (ev->key.keysym.mod & (KMOD_LCTRL | KMOD_RCTRL)) {
+ switch(ev->key.keysym.sym) {
+ case SDLK_UP: keysym = QEMU_KEY_CTRL_UP; break;
+ case SDLK_DOWN: keysym = QEMU_KEY_CTRL_DOWN; break;
+ case SDLK_LEFT: keysym = QEMU_KEY_CTRL_LEFT; break;
+ case SDLK_RIGHT: keysym = QEMU_KEY_CTRL_RIGHT; break;
+ case SDLK_HOME: keysym = QEMU_KEY_CTRL_HOME; break;
+ case SDLK_END: keysym = QEMU_KEY_CTRL_END; break;
+ case SDLK_PAGEUP: keysym = QEMU_KEY_CTRL_PAGEUP; break;
+ case SDLK_PAGEDOWN: keysym = QEMU_KEY_CTRL_PAGEDOWN; break;
+ default: break;
+ }
+ } else {
+ switch(ev->key.keysym.sym) {
+ case SDLK_UP: keysym = QEMU_KEY_UP; break;
+ case SDLK_DOWN: keysym = QEMU_KEY_DOWN; break;
+ case SDLK_LEFT: keysym = QEMU_KEY_LEFT; break;
+ case SDLK_RIGHT: keysym = QEMU_KEY_RIGHT; break;
+ case SDLK_HOME: keysym = QEMU_KEY_HOME; break;
+ case SDLK_END: keysym = QEMU_KEY_END; break;
+ case SDLK_PAGEUP: keysym = QEMU_KEY_PAGEUP; break;
+ case SDLK_PAGEDOWN: keysym = QEMU_KEY_PAGEDOWN; break;
+ case SDLK_BACKSPACE: keysym = QEMU_KEY_BACKSPACE; break; case SDLK_DELETE: keysym = QEMU_KEY_DELETE; break;
+ default: break;
+ }
+ }
+ if (keysym) {
+ kbd_put_keysym(keysym);
+ } else if (ev->key.keysym.unicode != 0) {
+ kbd_put_keysym(ev->key.keysym.unicode);
+ }
+ }
+ } else if (ev->type == SDL_KEYUP) {
+ mod_state = (ev->key.keysym.mod & gui_grab_code);
+ if (!mod_state) {
+ if (gui_key_modifier_pressed) {
+ gui_key_modifier_pressed = 0;
+ if (gui_keysym == 0) {
+ /* exit/enter grab if pressing Ctrl-Alt */
+ if (!gui_grab)
+ sdl_grab_start();
+ else
+ sdl_grab_end();
+ /* SDL does not send back all the
+ modifiers key, so we must correct it */
+ reset_keys();
+ break;
+ }
+ gui_keysym = 0;
+ }
+ }
+ }
+ if (is_active_console(vga_console))
+ sdl_process_key(&ev->key);
+ break;
+ case SDL_QUIT:
+ qemu_system_shutdown_request();
+ break;
+ case SDL_MOUSEMOTION:
+ if (gui_grab) {
+ sdl_send_mouse_event();
+ }
+ break;
+ case SDL_MOUSEBUTTONDOWN:
+ case SDL_MOUSEBUTTONUP:
+ {
+ SDL_MouseButtonEvent *bev = &ev->button;
+ if (!gui_grab) {
+ if (ev->type == SDL_MOUSEBUTTONDOWN &&
+ (bev->state & SDL_BUTTON_LMASK)) {
+ /* start grabbing all events */
+ sdl_grab_start();
+ }
+ } else {
+ sdl_send_mouse_event();
+ }
+ }
+ break;
+ case SDL_ACTIVEEVENT:
+ if (gui_grab && (ev->active.gain & SDL_ACTIVEEVENTMASK) == 0 &&
+ !gui_fullscreen_initial_grab) {
+ sdl_grab_end();
+ }
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+static void sdl_cleanup(void)
+{
+ SDL_Quit();
+}
+
+void sdl_display_init(DisplayState *ds, int full_screen)
+{
+ int flags;
+
+ if(keyboard_layout)
+ kbd_layout=init_keyboard_layout(keyboard_layout);
+
+ flags = SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE;
+ if (SDL_Init (flags)) {
+ fprintf(stderr, "Could not initialize SDL - exiting\n");
+ exit(1);
+ }
+#ifndef _WIN32
+ /* NOTE: we still want Ctrl-C to work, so we undo the SDL redirections */
+ signal(SIGINT, SIG_DFL);
+ signal(SIGQUIT, SIG_DFL);
+#endif
+
+ ds->dpy_update = sdl_update;
+ ds->dpy_resize = sdl_resize;
+ ds->dpy_refresh = sdl_refresh;
+
+ sdl_resize(ds, 640, 400);
+ sdl_update_caption();
+ SDL_EnableKeyRepeat(250, 50);
+ SDL_EnableUNICODE(1);
+ gui_grab = 0;
+
+ atexit(sdl_cleanup);
+ if (full_screen) {
+ gui_fullscreen = 1;
+ gui_fullscreen_initial_grab = 1;
+ sdl_grab_start();
+ }
+}
--- /dev/null
+#!/bin/sh
+
+. /etc/rc.d/init.d/functions
+
+qemubin=/usr/bin/qemu-dm
+
+ulimit -c unlimited
+
+# Use this for debugging:
+#gdb --args /usr/sbin/qemu-dm -hda /var/images/qemu-linux.img -nographic \
+# -serial pty -l 'ioport,int' $*
+
+while getopts ":f:" opt;
+do
+ case $opt in
+ f) QEMUCONFIGFILE=$OPTARG;shift;shift;;
+ \?) echo;;
+ esac
+done
+
+echo $QEMUCONFIGFILE
+if [ ! -z $QEMUCONFIGFILE ];then
+ . $QEMUCONFIGFILE
+else
+ echo "no config file specified!" > /dev/tty
+ echo "no config file specified!" >> /tmp/qemustart.log
+ exit
+fi
+
+PARMETER=""
+
+if [ ! -z $hda ];then
+PARMETER="$PARMETER -hda $hda"
+fi
+
+if [ ! -z $hdb ];then
+PARMETER="$PARMETER -hdb $hdb"
+fi
+
+if [ ! -z $hdc ];then
+PARMETER="$PARMETER -hdc $hdc"
+fi
+
+if [ ! -z $hdd ];then
+PARMETER="$PARMETER -hdd $hdd"
+fi
+
+if [ ! -z $nographic ] && [ $nographic -eq 1 ];then
+PARMETER="$PARMETER -nographic"
+fi
+
+vnc=${vnc:=1}
+sdl=${sdl:=0}
+if qemu-dm 2>&1 |grep vnc > /dev/null;then
+ if [ $vnc -eq 1 ] && [ $sdl -eq 1 ];then
+ PARMETER="$PARMETER -vnc-and-sdl -k en-us"
+ elif [ $vnc -eq 1 ];then
+ PARMETER="$PARMETER -vnc -k en-us"
+ fi
+fi
+
+#optional cmdline for qemu
+# -nographic \
+# -serial pty \
+
+
+PARMETER="$PARMETER -l int $*";
+echo "$qemubin $PARMETER" >>/tmp/qemustart.log
+$qemubin $PARMETER &
--- /dev/null
+/*
+ * i386 helpers (without register variable usage)
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * Main cpu loop for handling I/O requests coming from a virtual machine
+ * Copyright © 2004, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU Lesser General Public License,
+ * version 2.1, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307 USA.
+ */
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <signal.h>
+#include <assert.h>
+
+#include <limits.h>
+#include <fcntl.h>
+
+#include "xc.h"
+#include <io/ioreq.h>
+
+#include "cpu.h"
+#include "exec-all.h"
+
+//#define DEBUG_MMU
+
+#ifdef USE_CODE_COPY
+#include <asm/ldt.h>
+#include <linux/unistd.h>
+#include <linux/version.h>
+
+#include <sys/ioctl.h>
+/* According to POSIX 1003.1-2001 */
+#include <sys/select.h>
+
+/* According to earlier standards */
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <values.h>
+
+_syscall3(int, modify_ldt, int, func, void *, ptr, unsigned long, bytecount)
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 66)
+#define modify_ldt_ldt_s user_desc
+#endif
+#endif /* USE_CODE_COPY */
+
+void *shared_page;
+
+CPUX86State *cpu_86_init(void)
+{
+ CPUX86State *env;
+ static int inited;
+
+ cpu_exec_init();
+
+ env = malloc(sizeof(CPUX86State));
+ if (!env)
+ return NULL;
+ memset(env, 0, sizeof(CPUX86State));
+ /* init various static tables */
+ if (!inited) {
+ inited = 1;
+ }
+ cpu_single_env = env;
+ cpu_reset(env);
+ return env;
+}
+
+/* NOTE: must be called outside the CPU execute loop */
+void cpu_reset(CPUX86State *env)
+{
+}
+
+void cpu_x86_close(CPUX86State *env)
+{
+ free(env);
+}
+
+
+void cpu_dump_state(CPUState *env, FILE *f,
+ int (*cpu_fprintf)(FILE *f, const char *fmt, ...),
+ int flags)
+{
+}
+
+/***********************************************************/
+/* x86 mmu */
+/* XXX: add PGE support */
+
+void cpu_x86_set_a20(CPUX86State *env, int a20_state)
+{
+ a20_state = (a20_state != 0);
+ if (a20_state != ((env->a20_mask >> 20) & 1)) {
+#if defined(DEBUG_MMU)
+ printf("A20 update: a20=%d\n", a20_state);
+#endif
+ env->a20_mask = 0xffefffff | (a20_state << 20);
+ }
+}
+
+target_ulong cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
+{
+ return addr;
+}
+
+//the evtchn fd for polling
+int evtchn_fd = -1;
+//the evtchn port for polling the notification, should be inputed as bochs's parameter
+u16 ioreq_port = 0;
+
+void *shared_page = NULL;
+
+//some functions to handle the io req packet
+
+//get the ioreq packets from share mem
+ioreq_t* __cpu_get_ioreq(void)
+{
+ ioreq_t *req;
+ req = &((vcpu_iodata_t *) shared_page)->vp_ioreq;
+ if (req->state == STATE_IOREQ_READY) {
+ req->state = STATE_IOREQ_INPROCESS;
+ } else {
+ fprintf(logfile, "False I/O requrest ... in-service already: %x, pvalid: %x,port: %llx, data: %llx, count: %llx, size: %llx\n", req->state, req->pdata_valid, req->addr, req->u.data, req->count, req->size);
+ req = NULL;
+ }
+
+ return req;
+}
+
+//use poll to get the port notification
+//ioreq_vec--out,the
+//retval--the number of ioreq packet
+ioreq_t* cpu_get_ioreq(void)
+{
+ int rc;
+ u16 buf[2];
+ rc = read(evtchn_fd, buf, 2);
+ if (rc == 2 && buf[0] == ioreq_port){//got only one matched 16bit port index
+ // unmask the wanted port again
+ write(evtchn_fd, &ioreq_port, 2);
+
+ //get the io packet from shared memory
+ return __cpu_get_ioreq();
+ }
+
+ //read error or read nothing
+ return NULL;
+}
+
+unsigned long
+do_inp(CPUState *env, unsigned long addr, unsigned long size)
+{
+ switch(size) {
+ case 1:
+ return cpu_inb(env, addr);
+ case 2:
+ return cpu_inw(env, addr);
+ case 4:
+ return cpu_inl(env, addr);
+ default:
+ fprintf(logfile, "inp: bad size: %lx %lx\n", addr, size);
+ exit(-1);
+ }
+}
+
+void
+do_outp(CPUState *env, unsigned long addr, unsigned long size,
+ unsigned long val)
+{
+ switch(size) {
+ case 1:
+ return cpu_outb(env, addr, val);
+ case 2:
+ return cpu_outw(env, addr, val);
+ case 4:
+ return cpu_outl(env, addr, val);
+ default:
+ fprintf(logfile, "outp: bad size: %lx %lx\n", addr, size);
+ exit(-1);
+ }
+}
+
+extern void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf,
+ int len, int is_write);
+
+static inline void
+read_physical(target_phys_addr_t addr, unsigned long size, void *val)
+{
+ return cpu_physical_memory_rw(addr, val, size, 0);
+}
+
+static inline void
+write_physical(target_phys_addr_t addr, unsigned long size, void *val)
+{
+ return cpu_physical_memory_rw(addr, val, size, 1);
+}
+
+//send the ioreq to device model
+void cpu_dispatch_ioreq(CPUState *env, ioreq_t *req)
+{
+ int i;
+ int sign;
+
+ sign = (req->df) ? -1 : 1;
+
+ if ((!req->pdata_valid) && (req->dir == IOREQ_WRITE)) {
+ if (req->size != 4) {
+ // Bochs expects higher bits to be 0
+ req->u.data &= (1UL << (8 * req->size))-1;
+ }
+ }
+
+ if (req->port_mm == 0){//port io
+ if(req->dir == IOREQ_READ){//read
+ if (!req->pdata_valid) {
+ req->u.data = do_inp(env, req->addr, req->size);
+ } else {
+ unsigned long tmp;
+
+ for (i = 0; i < req->count; i++) {
+ tmp = do_inp(env, req->addr, req->size);
+ write_physical((target_phys_addr_t)req->u.pdata + (sign * i * req->size),
+ req->size, &tmp);
+ }
+ }
+ } else if(req->dir == IOREQ_WRITE) {
+ if (!req->pdata_valid) {
+ do_outp(env, req->addr, req->size, req->u.data);
+ } else {
+ for (i = 0; i < req->count; i++) {
+ unsigned long tmp;
+
+ read_physical((target_phys_addr_t)req->u.pdata + (sign * i * req->size), req->size,
+ &tmp);
+ do_outp(env, req->addr, req->size, tmp);
+ }
+ }
+
+ }
+ } else if (req->port_mm == 1){//memory map io
+ if (!req->pdata_valid) {
+ //handle stos
+ if(req->dir == IOREQ_READ) { //read
+ for (i = 0; i < req->count; i++) {
+ read_physical((target_phys_addr_t)req->addr + (sign * i * req->size), req->size, &req->u.data);
+ }
+ } else if(req->dir == IOREQ_WRITE) { //write
+ for (i = 0; i < req->count; i++) {
+ write_physical((target_phys_addr_t)req->addr + (sign * i * req->size), req->size, &req->u.data);
+ }
+ }
+ } else {
+ //handle movs
+ unsigned long tmp;
+ if (req->dir == IOREQ_READ) {
+ for (i = 0; i < req->count; i++) {
+ read_physical((target_phys_addr_t)req->addr + (sign * i * req->size), req->size, &tmp);
+ write_physical((target_phys_addr_t)req->u.pdata + (sign * i * req->size), req->size, &tmp);
+ }
+ } else if (req->dir == IOREQ_WRITE) {
+ for (i = 0; i < req->count; i++) {
+ read_physical((target_phys_addr_t)req->u.pdata + (sign * i * req->size), req->size, &tmp);
+ write_physical((target_phys_addr_t)req->addr + (sign * i * req->size), req->size, &tmp);
+ }
+ }
+ }
+ }
+ /* No state change if state = STATE_IORESP_HOOK */
+ if (req->state == STATE_IOREQ_INPROCESS)
+ req->state = STATE_IORESP_READY;
+ env->send_event = 1;
+}
+
+void
+cpu_handle_ioreq(CPUState *env)
+{
+ ioreq_t *req = cpu_get_ioreq();
+ if (req)
+ cpu_dispatch_ioreq(env, req);
+}
+
+void
+cpu_timer_handler(CPUState *env)
+{
+ cpu_handle_ioreq(env);
+}
+
+int xc_handle;
+
+#include <asm/bitops.h>
+
+void
+do_interrupt(CPUState *env, int vector)
+{
+ unsigned long *intr;
+
+ // Send a message on the event channel. Add the vector to the shared mem
+ // page.
+
+ intr = &(((vcpu_iodata_t *) shared_page)->vp_intr[0]);
+ set_bit(vector, intr);
+ fprintf(logfile, "injecting vector: %x\n", vector);
+ env->send_event = 1;
+}
+
+//static unsigned long tsc_per_tick = 1; /* XXX: calibrate */
+
+int main_loop(void)
+{
+ int vector;
+ fd_set rfds;
+ struct timeval tv;
+ extern CPUState *global_env;
+ extern int vm_running;
+ extern int shutdown_requested;
+ CPUState *env = global_env;
+ int retval;
+ extern void main_loop_wait(int);
+
+ /* Watch stdin (fd 0) to see when it has input. */
+ FD_ZERO(&rfds);
+
+ while (1) {
+ if (vm_running) {
+ if (shutdown_requested) {
+ break;
+ }
+ }
+
+ /* Wait up to one seconds. */
+ tv.tv_sec = 0;
+ tv.tv_usec = 100000;
+ FD_SET(evtchn_fd, &rfds);
+
+ env->send_event = 0;
+ retval = select(evtchn_fd+1, &rfds, NULL, NULL, &tv);
+ if (retval == -1) {
+ perror("select");
+ return 0;
+ }
+
+#if __WORDSIZE == 32
+#define ULONGLONG_MAX 0xffffffffffffffffULL
+#else
+#define ULONGLONG_MAX ULONG_MAX
+#endif
+
+ main_loop_wait(0);
+
+ cpu_timer_handler(env);
+ if (env->interrupt_request & CPU_INTERRUPT_HARD) {
+ env->interrupt_request &= ~CPU_INTERRUPT_HARD;
+ vector = cpu_get_pic_interrupt(env);
+ do_interrupt(env, vector);
+ }
+
+ if (env->send_event) {
+ int ret;
+ ret = xc_evtchn_send(xc_handle, ioreq_port);
+ if (ret == -1) {
+ fprintf(logfile, "evtchn_send failed on port: %d\n", ioreq_port);
+ }
+ }
+ }
+ return 0;
+}
+
+CPUState *
+cpu_init()
+{
+ CPUX86State *env;
+
+ cpu_exec_init();
+
+ env = malloc(sizeof(CPUX86State));
+ if (!env)
+ return NULL;
+ memset(env, 0, sizeof(CPUX86State));
+
+ cpu_single_env = env;
+
+ if (evtchn_fd != -1)//the evtchn has been opened by another cpu object
+ return NULL;
+
+ //use nonblock reading not polling, may change in future.
+ evtchn_fd = open("/dev/xen/evtchn", O_RDWR|O_NONBLOCK);
+ if (evtchn_fd == -1) {
+ perror("open");
+ return NULL;
+ }
+
+ fprintf(logfile, "listening to port: %d\n", ioreq_port);
+ /*unmask the wanted port -- bind*/
+ if (ioctl(evtchn_fd, ('E'<<8)|2, ioreq_port) == -1) {
+ perror("ioctl");
+ return NULL;
+ }
+
+ return env;
+}
--- /dev/null
+#!/bin/sh
+
+#. /etc/rc.d/init.d/functions
+#ulimit -c unlimited
+
+echo 'config qemu network with xen bridge for '
+echo $*
+
+ifconfig $1 0.0.0.0 up
+brctl addif xen-br0 $1
--- /dev/null
+-include ../config-host.mak
+
+CFLAGS=-Wall -O2 -g
+LDFLAGS=
+
+ifeq ($(ARCH),i386)
+TESTS=linux-test testthread sha1-i386 test-i386 runcom
+endif
+TESTS+=sha1# test_path
+#TESTS+=test_path
+
+QEMU=../i386-user/qemu-i386
+
+all: $(TESTS)
+
+hello-i386: hello-i386.c
+ $(CC) -nostdlib $(CFLAGS) -static $(LDFLAGS) -o $@ $<
+ strip $@
+
+testthread: testthread.c
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< -lpthread
+
+test_path: test_path.c
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<
+ ./$@ || { rm $@; exit 1; }
+
+# i386 emulation test (test various opcodes) */
+test-i386: test-i386.c test-i386-code16.S test-i386-vm86.S \
+ test-i386.h test-i386-shift.h test-i386-muldiv.h
+ $(CC) $(CFLAGS) $(LDFLAGS) -static -o $@ test-i386.c \
+ test-i386-code16.S test-i386-vm86.S -lm
+
+ifeq ($(ARCH),i386)
+test: test-i386
+ ./test-i386 > test-i386.ref
+else
+test:
+endif
+ $(QEMU) test-i386 > test-i386.out
+ @if diff -u test-i386.ref test-i386.out ; then echo "Auto Test OK"; fi
+ifeq ($(ARCH),i386)
+ $(QEMU) -no-code-copy test-i386 > test-i386.out
+ @if diff -u test-i386.ref test-i386.out ; then echo "Auto Test OK (no code copy)"; fi
+endif
+
+# generic Linux and CPU test
+linux-test: linux-test.c
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< -lm
+
+# speed test
+sha1-i386: sha1.c
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<
+
+sha1: sha1.c
+ $(HOST_CC) $(CFLAGS) $(LDFLAGS) -o $@ $<
+
+speed: sha1 sha1-i386
+ time ./sha1
+ time $(QEMU) ./sha1-i386
+
+# vm86 test
+runcom: runcom.c
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<
+
+# NOTE: -fomit-frame-pointer is currently needed : this is a bug in libqemu
+qruncom: qruncom.c ../i386-user/libqemu.a
+ $(CC) $(CFLAGS) -fomit-frame-pointer $(LDFLAGS) -I../target-i386 -I.. -I../i386-user \
+ -o $@ $< -L../i386-user -lqemu -lm
+
+# arm test
+hello-arm: hello-arm.o
+ arm-linux-ld -o $@ $<
+
+hello-arm.o: hello-arm.c
+ arm-linux-gcc -Wall -g -O2 -c -o $@ $<
+
+# XXX: find a way to compile easily a test for each arch
+test2:
+ @for arch in i386 arm sparc ppc; do \
+ ../$${arch}-user/qemu-$${arch} $${arch}/ls -l linux-test.c ; \
+ done
+
+clean:
+ rm -f *~ *.o test-i386.out test-i386.ref qruncom $(TESTS)
--- /dev/null
+#define __NR_SYSCALL_BASE 0x900000
+#define __NR_exit1 (__NR_SYSCALL_BASE+ 1)
+#define __NR_write (__NR_SYSCALL_BASE+ 4)
+
+#define __sys2(x) #x
+#define __sys1(x) __sys2(x)
+
+#ifndef __syscall
+#define __syscall(name) "swi\t" __sys1(__NR_##name) "\n\t"
+#endif
+
+#define __syscall_return(type, res) \
+do { \
+ return (type) (res); \
+} while (0)
+
+#define _syscall0(type,name) \
+type name(void) { \
+ long __res; \
+ __asm__ __volatile__ ( \
+ __syscall(name) \
+ "mov %0,r0" \
+ :"=r" (__res) : : "r0","lr"); \
+ __syscall_return(type,__res); \
+}
+
+#define _syscall1(type,name,type1,arg1) \
+type name(type1 arg1) { \
+ long __res; \
+ __asm__ __volatile__ ( \
+ "mov\tr0,%1\n\t" \
+ __syscall(name) \
+ "mov %0,r0" \
+ : "=r" (__res) \
+ : "r" ((long)(arg1)) \
+ : "r0","lr"); \
+ __syscall_return(type,__res); \
+}
+
+#define _syscall2(type,name,type1,arg1,type2,arg2) \
+type name(type1 arg1,type2 arg2) { \
+ long __res; \
+ __asm__ __volatile__ ( \
+ "mov\tr0,%1\n\t" \
+ "mov\tr1,%2\n\t" \
+ __syscall(name) \
+ "mov\t%0,r0" \
+ : "=r" (__res) \
+ : "r" ((long)(arg1)),"r" ((long)(arg2)) \
+ : "r0","r1","lr"); \
+ __syscall_return(type,__res); \
+}
+
+
+#define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \
+type name(type1 arg1,type2 arg2,type3 arg3) { \
+ long __res; \
+ __asm__ __volatile__ ( \
+ "mov\tr0,%1\n\t" \
+ "mov\tr1,%2\n\t" \
+ "mov\tr2,%3\n\t" \
+ __syscall(name) \
+ "mov\t%0,r0" \
+ : "=r" (__res) \
+ : "r" ((long)(arg1)),"r" ((long)(arg2)),"r" ((long)(arg3)) \
+ : "r0","r1","r2","lr"); \
+ __syscall_return(type,__res); \
+}
+
+
+#define _syscall4(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4) \
+type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4) { \
+ long __res; \
+ __asm__ __volatile__ ( \
+ "mov\tr0,%1\n\t" \
+ "mov\tr1,%2\n\t" \
+ "mov\tr2,%3\n\t" \
+ "mov\tr3,%4\n\t" \
+ __syscall(name) \
+ "mov\t%0,r0" \
+ : "=r" (__res) \
+ : "r" ((long)(arg1)),"r" ((long)(arg2)),"r" ((long)(arg3)),"r" ((long)(arg4)) \
+ : "r0","r1","r2","r3","lr"); \
+ __syscall_return(type,__res); \
+}
+
+
+#define _syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,type5,arg5) \
+type name(type1 arg1, type2 arg2, type3 arg3, type4 arg4, type5 arg5) { \
+ long __res; \
+ __asm__ __volatile__ ( \
+ "mov\tr0,%1\n\t" \
+ "mov\tr1,%2\n\t" \
+ "mov\tr2,%3\n\t" \
+ "mov\tr3,%4\n\t" \
+ "mov\tr4,%5\n\t" \
+ __syscall(name) \
+ "mov\t%0,r0" \
+ : "=r" (__res) \
+ : "r" ((long)(arg1)),"r" ((long)(arg2)),"r" ((long)(arg3)),"r" ((long)(arg4)), \
+ "r" ((long)(arg5)) \
+ : "r0","r1","r2","r3","r4","lr"); \
+ __syscall_return(type,__res); \
+}
+
+_syscall1(int,exit1,int,status);
+_syscall3(int,write,int,fd,const char *,buf, int, len);
+
+void _start(void)
+{
+ write(1, "Hello World\n", 12);
+ exit1(0);
+}
--- /dev/null
+#include <asm/unistd.h>
+
+extern inline volatile void exit(int status)
+{
+ int __res;
+ __asm__ volatile ("movl %%ecx,%%ebx\n"\
+ "int $0x80" \
+ : "=a" (__res) : "0" (__NR_exit),"c" ((long)(status)));
+}
+
+extern inline int write(int fd, const char * buf, int len)
+{
+ int status;
+ __asm__ volatile ("pushl %%ebx\n"\
+ "movl %%esi,%%ebx\n"\
+ "int $0x80\n" \
+ "popl %%ebx\n"\
+ : "=a" (status) \
+ : "0" (__NR_write),"S" ((long)(fd)),"c" ((long)(buf)),"d" ((long)(len)));
+}
+
+void _start(void)
+{
+ write(1, "Hello World\n", 12);
+ exit(0);
+}
--- /dev/null
+/*
+ * linux and CPU test
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <utime.h>
+#include <time.h>
+#include <sys/time.h>
+#include <sys/uio.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <sched.h>
+#include <dirent.h>
+#include <setjmp.h>
+#include <sys/shm.h>
+
+#define TESTPATH "/tmp/linux-test.tmp"
+#define TESTPORT 7654
+#define STACK_SIZE 16384
+
+void error1(const char *filename, int line, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ fprintf(stderr, "%s:%d: ", filename, line);
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, "\n");
+ va_end(ap);
+ exit(1);
+}
+
+int __chk_error(const char *filename, int line, int ret)
+{
+ if (ret < 0) {
+ error1(filename, line, "%m (ret=%d, errno=%d)",
+ ret, errno);
+ }
+ return ret;
+}
+
+#define error(fmt, args...) error1(__FILE__, __LINE__, fmt, ##args)
+
+#define chk_error(ret) __chk_error(__FILE__, __LINE__, (ret))
+
+/*******************************************************/
+
+#define FILE_BUF_SIZE 300
+
+void test_file(void)
+{
+ int fd, i, len, ret;
+ uint8_t buf[FILE_BUF_SIZE];
+ uint8_t buf2[FILE_BUF_SIZE];
+ uint8_t buf3[FILE_BUF_SIZE];
+ char cur_dir[1024];
+ struct stat st;
+ struct utimbuf tbuf;
+ struct iovec vecs[2];
+ DIR *dir;
+ struct dirent *de;
+
+ /* clean up, just in case */
+ unlink(TESTPATH "/file1");
+ unlink(TESTPATH "/file2");
+ unlink(TESTPATH "/file3");
+ rmdir(TESTPATH);
+
+ if (getcwd(cur_dir, sizeof(cur_dir)) == NULL)
+ error("getcwd");
+
+ chk_error(mkdir(TESTPATH, 0755));
+
+ chk_error(chdir(TESTPATH));
+
+ /* open/read/write/close/readv/writev/lseek */
+
+ fd = chk_error(open("file1", O_WRONLY | O_TRUNC | O_CREAT, 0644));
+ for(i=0;i < FILE_BUF_SIZE; i++)
+ buf[i] = i;
+ len = chk_error(write(fd, buf, FILE_BUF_SIZE / 2));
+ if (len != (FILE_BUF_SIZE / 2))
+ error("write");
+ vecs[0].iov_base = buf + (FILE_BUF_SIZE / 2);
+ vecs[0].iov_len = 16;
+ vecs[1].iov_base = buf + (FILE_BUF_SIZE / 2) + 16;
+ vecs[1].iov_len = (FILE_BUF_SIZE / 2) - 16;
+ len = chk_error(writev(fd, vecs, 2));
+ if (len != (FILE_BUF_SIZE / 2))
+ error("writev");
+ chk_error(close(fd));
+
+ chk_error(rename("file1", "file2"));
+
+ fd = chk_error(open("file2", O_RDONLY));
+
+ len = chk_error(read(fd, buf2, FILE_BUF_SIZE));
+ if (len != FILE_BUF_SIZE)
+ error("read");
+ if (memcmp(buf, buf2, FILE_BUF_SIZE) != 0)
+ error("memcmp");
+
+#define FOFFSET 16
+ ret = chk_error(lseek(fd, FOFFSET, SEEK_SET));
+ if (ret != 16)
+ error("lseek");
+ vecs[0].iov_base = buf3;
+ vecs[0].iov_len = 32;
+ vecs[1].iov_base = buf3 + 32;
+ vecs[1].iov_len = FILE_BUF_SIZE - FOFFSET - 32;
+ len = chk_error(readv(fd, vecs, 2));
+ if (len != FILE_BUF_SIZE - FOFFSET)
+ error("readv");
+ if (memcmp(buf + FOFFSET, buf3, FILE_BUF_SIZE - FOFFSET) != 0)
+ error("memcmp");
+
+ chk_error(close(fd));
+
+ /* access */
+ chk_error(access("file2", R_OK));
+
+ /* stat/chmod/utime/truncate */
+
+ chk_error(chmod("file2", 0600));
+ tbuf.actime = 1001;
+ tbuf.modtime = 1000;
+ chk_error(truncate("file2", 100));
+ chk_error(utime("file2", &tbuf));
+ chk_error(stat("file2", &st));
+ if (st.st_size != 100)
+ error("stat size");
+ if (!S_ISREG(st.st_mode))
+ error("stat mode");
+ if ((st.st_mode & 0777) != 0600)
+ error("stat mode2");
+ if (st.st_atime != 1001 ||
+ st.st_mtime != 1000)
+ error("stat time");
+
+ chk_error(stat(TESTPATH, &st));
+ if (!S_ISDIR(st.st_mode))
+ error("stat mode");
+
+ /* fstat */
+ fd = chk_error(open("file2", O_RDWR));
+ chk_error(ftruncate(fd, 50));
+ chk_error(fstat(fd, &st));
+ chk_error(close(fd));
+
+ if (st.st_size != 50)
+ error("stat size");
+ if (!S_ISREG(st.st_mode))
+ error("stat mode");
+
+ /* symlink/lstat */
+ chk_error(symlink("file2", "file3"));
+ chk_error(lstat("file3", &st));
+ if (!S_ISLNK(st.st_mode))
+ error("stat mode");
+
+ /* getdents */
+ dir = opendir(TESTPATH);
+ if (!dir)
+ error("opendir");
+ len = 0;
+ for(;;) {
+ de = readdir(dir);
+ if (!de)
+ break;
+ if (strcmp(de->d_name, ".") != 0 &&
+ strcmp(de->d_name, "..") != 0 &&
+ strcmp(de->d_name, "file2") != 0 &&
+ strcmp(de->d_name, "file3") != 0)
+ error("readdir");
+ len++;
+ }
+ closedir(dir);
+ if (len != 4)
+ error("readdir");
+
+ chk_error(unlink("file3"));
+ chk_error(unlink("file2"));
+ chk_error(chdir(cur_dir));
+ chk_error(rmdir(TESTPATH));
+}
+
+void test_fork(void)
+{
+ int pid, status;
+
+ pid = chk_error(fork());
+ if (pid == 0) {
+ /* child */
+ exit(2);
+ }
+ chk_error(waitpid(pid, &status, 0));
+ if (!WIFEXITED(status) || WEXITSTATUS(status) != 2)
+ error("waitpid status=0x%x", status);
+}
+
+void test_time(void)
+{
+ struct timeval tv, tv2;
+ struct timespec ts, rem;
+ struct rusage rusg1, rusg2;
+ int ti, i;
+
+ chk_error(gettimeofday(&tv, NULL));
+ rem.tv_sec = 1;
+ ts.tv_sec = 0;
+ ts.tv_nsec = 20 * 1000000;
+ chk_error(nanosleep(&ts, &rem));
+ if (rem.tv_sec != 1)
+ error("nanosleep");
+ chk_error(gettimeofday(&tv2, NULL));
+ ti = tv2.tv_sec - tv.tv_sec;
+ if (ti >= 2)
+ error("gettimeofday");
+
+ chk_error(getrusage(RUSAGE_SELF, &rusg1));
+ for(i = 0;i < 10000; i++);
+ chk_error(getrusage(RUSAGE_SELF, &rusg2));
+ if ((rusg2.ru_utime.tv_sec - rusg1.ru_utime.tv_sec) < 0 ||
+ (rusg2.ru_stime.tv_sec - rusg1.ru_stime.tv_sec) < 0)
+ error("getrusage");
+}
+
+void pstrcpy(char *buf, int buf_size, const char *str)
+{
+ int c;
+ char *q = buf;
+
+ if (buf_size <= 0)
+ return;
+
+ for(;;) {
+ c = *str++;
+ if (c == 0 || q >= buf + buf_size - 1)
+ break;
+ *q++ = c;
+ }
+ *q = '\0';
+}
+
+/* strcat and truncate. */
+char *pstrcat(char *buf, int buf_size, const char *s)
+{
+ int len;
+ len = strlen(buf);
+ if (len < buf_size)
+ pstrcpy(buf + len, buf_size - len, s);
+ return buf;
+}
+
+int server_socket(void)
+{
+ int val, fd;
+ struct sockaddr_in sockaddr;
+
+ /* server socket */
+ fd = chk_error(socket(PF_INET, SOCK_STREAM, 0));
+
+ val = 1;
+ chk_error(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)));
+
+ sockaddr.sin_family = AF_INET;
+ sockaddr.sin_port = htons(TESTPORT);
+ sockaddr.sin_addr.s_addr = 0;
+ chk_error(bind(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)));
+ chk_error(listen(fd, 0));
+ return fd;
+
+}
+
+int client_socket(void)
+{
+ int fd;
+ struct sockaddr_in sockaddr;
+
+ /* server socket */
+ fd = chk_error(socket(PF_INET, SOCK_STREAM, 0));
+ sockaddr.sin_family = AF_INET;
+ sockaddr.sin_port = htons(TESTPORT);
+ inet_aton("127.0.0.1", &sockaddr.sin_addr);
+ chk_error(connect(fd, (struct sockaddr *)&sockaddr, sizeof(sockaddr)));
+ return fd;
+}
+
+const char socket_msg[] = "hello socket\n";
+
+void test_socket(void)
+{
+ int server_fd, client_fd, fd, pid, ret, val;
+ struct sockaddr_in sockaddr;
+ socklen_t len;
+ char buf[512];
+
+ server_fd = server_socket();
+
+ /* test a few socket options */
+ len = sizeof(val);
+ chk_error(getsockopt(server_fd, SOL_SOCKET, SO_TYPE, &val, &len));
+ if (val != SOCK_STREAM)
+ error("getsockopt");
+
+ pid = chk_error(fork());
+ if (pid == 0) {
+ client_fd = client_socket();
+ send(client_fd, socket_msg, sizeof(socket_msg), 0);
+ close(client_fd);
+ exit(0);
+ }
+ len = sizeof(sockaddr);
+ fd = chk_error(accept(server_fd, (struct sockaddr *)&sockaddr, &len));
+
+ ret = chk_error(recv(fd, buf, sizeof(buf), 0));
+ if (ret != sizeof(socket_msg))
+ error("recv");
+ if (memcmp(buf, socket_msg, sizeof(socket_msg)) != 0)
+ error("socket_msg");
+ chk_error(close(fd));
+ chk_error(close(server_fd));
+}
+
+#define WCOUNT_MAX 512
+
+void test_pipe(void)
+{
+ fd_set rfds, wfds;
+ int fds[2], fd_max, ret;
+ uint8_t ch;
+ int wcount, rcount;
+
+ chk_error(pipe(fds));
+ chk_error(fcntl(fds[0], F_SETFL, O_NONBLOCK));
+ chk_error(fcntl(fds[1], F_SETFL, O_NONBLOCK));
+ wcount = 0;
+ rcount = 0;
+ for(;;) {
+ FD_ZERO(&rfds);
+ fd_max = fds[0];
+ FD_SET(fds[0], &rfds);
+
+ FD_ZERO(&wfds);
+ FD_SET(fds[1], &wfds);
+ if (fds[1] > fd_max)
+ fd_max = fds[1];
+
+ ret = chk_error(select(fd_max + 1, &rfds, &wfds, NULL, NULL));
+ if (ret > 0) {
+ if (FD_ISSET(fds[0], &rfds)) {
+ chk_error(read(fds[0], &ch, 1));
+ rcount++;
+ if (rcount >= WCOUNT_MAX)
+ break;
+ }
+ if (FD_ISSET(fds[1], &wfds)) {
+ ch = 'a';
+ chk_error(write(fds[0], &ch, 1));
+ wcount++;
+ }
+ }
+ }
+ chk_error(close(fds[0]));
+ chk_error(close(fds[1]));
+}
+
+int thread1_res;
+int thread2_res;
+
+int thread1_func(void *arg)
+{
+ int i;
+ for(i=0;i<5;i++) {
+ thread1_res++;
+ usleep(10 * 1000);
+ }
+ return 0;
+}
+
+int thread2_func(void *arg)
+{
+ int i;
+ for(i=0;i<6;i++) {
+ thread2_res++;
+ usleep(10 * 1000);
+ }
+ return 0;
+}
+
+void test_clone(void)
+{
+ uint8_t *stack1, *stack2;
+ int pid1, pid2, status1, status2;
+
+ stack1 = malloc(STACK_SIZE);
+ pid1 = chk_error(clone(thread1_func, stack1 + STACK_SIZE,
+ CLONE_VM | CLONE_FS | CLONE_FILES | SIGCHLD, "hello1"));
+
+ stack2 = malloc(STACK_SIZE);
+ pid2 = chk_error(clone(thread2_func, stack2 + STACK_SIZE,
+ CLONE_VM | CLONE_FS | CLONE_FILES | SIGCHLD, "hello2"));
+
+ while (waitpid(pid1, &status1, 0) != pid1);
+ while (waitpid(pid2, &status2, 0) != pid2);
+ if (thread1_res != 5 ||
+ thread2_res != 6)
+ error("clone");
+}
+
+/***********************************/
+
+volatile int alarm_count;
+jmp_buf jmp_env;
+
+void sig_alarm(int sig)
+{
+ if (sig != SIGALRM)
+ error("signal");
+ alarm_count++;
+}
+
+void sig_segv(int sig, siginfo_t *info, void *puc)
+{
+ if (sig != SIGSEGV)
+ error("signal");
+ longjmp(jmp_env, 1);
+}
+
+void test_signal(void)
+{
+ struct sigaction act;
+ struct itimerval it, oit;
+
+ /* timer test */
+
+ alarm_count = 0;
+
+ act.sa_handler = sig_alarm;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+ chk_error(sigaction(SIGALRM, &act, NULL));
+
+ it.it_interval.tv_sec = 0;
+ it.it_interval.tv_usec = 10 * 1000;
+ it.it_value.tv_sec = 0;
+ it.it_value.tv_usec = 10 * 1000;
+ chk_error(setitimer(ITIMER_REAL, &it, NULL));
+ chk_error(getitimer(ITIMER_REAL, &oit));
+ if (oit.it_value.tv_sec != it.it_value.tv_sec ||
+ oit.it_value.tv_usec != it.it_value.tv_usec)
+ error("itimer");
+
+ while (alarm_count < 5) {
+ usleep(10 * 1000);
+ }
+
+ it.it_interval.tv_sec = 0;
+ it.it_interval.tv_usec = 0;
+ it.it_value.tv_sec = 0;
+ it.it_value.tv_usec = 0;
+ memset(&oit, 0xff, sizeof(oit));
+ chk_error(setitimer(ITIMER_REAL, &it, &oit));
+ if (oit.it_value.tv_sec != 0 ||
+ oit.it_value.tv_usec != 10 * 1000)
+ error("setitimer");
+
+ /* SIGSEGV test */
+ act.sa_sigaction = sig_segv;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_SIGINFO;
+ chk_error(sigaction(SIGSEGV, &act, NULL));
+ if (setjmp(jmp_env) == 0) {
+ *(uint8_t *)0 = 0;
+ }
+
+ act.sa_handler = SIG_DFL;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+ chk_error(sigaction(SIGSEGV, &act, NULL));
+}
+
+#define SHM_SIZE 32768
+
+void test_shm(void)
+{
+ void *ptr;
+ int shmid;
+
+ shmid = chk_error(shmget(IPC_PRIVATE, SHM_SIZE, IPC_CREAT | 0777));
+ ptr = shmat(shmid, NULL, 0);
+ if (!ptr)
+ error("shmat");
+
+ memset(ptr, 0, SHM_SIZE);
+
+ chk_error(shmctl(shmid, IPC_RMID, 0));
+ chk_error(shmdt(ptr));
+}
+
+int main(int argc, char **argv)
+{
+ test_file();
+ test_fork();
+ test_time();
+ test_socket();
+ // test_clone();
+ test_signal();
+ test_shm();
+ return 0;
+}
--- /dev/null
+/*
+ * Example of use of user mode libqemu: launch a basic .com DOS
+ * executable
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <signal.h>
+
+#include "cpu.h"
+
+//#define SIGTEST
+
+CPUState *cpu_single_env = NULL;
+
+void cpu_outb(CPUState *env, int addr, int val)
+{
+ fprintf(stderr, "outb: port=0x%04x, data=%02x\n", addr, val);
+}
+
+void cpu_outw(CPUState *env, int addr, int val)
+{
+ fprintf(stderr, "outw: port=0x%04x, data=%04x\n", addr, val);
+}
+
+void cpu_outl(CPUState *env, int addr, int val)
+{
+ fprintf(stderr, "outl: port=0x%04x, data=%08x\n", addr, val);
+}
+
+int cpu_inb(CPUState *env, int addr)
+{
+ fprintf(stderr, "inb: port=0x%04x\n", addr);
+ return 0;
+}
+
+int cpu_inw(CPUState *env, int addr)
+{
+ fprintf(stderr, "inw: port=0x%04x\n", addr);
+ return 0;
+}
+
+int cpu_inl(CPUState *env, int addr)
+{
+ fprintf(stderr, "inl: port=0x%04x\n", addr);
+ return 0;
+}
+
+int cpu_get_pic_interrupt(CPUState *env)
+{
+ return -1;
+}
+
+uint64_t cpu_get_tsc(CPUState *env)
+{
+ return 0;
+}
+
+static void set_gate(void *ptr, unsigned int type, unsigned int dpl,
+ unsigned long addr, unsigned int sel)
+{
+ unsigned int e1, e2;
+ e1 = (addr & 0xffff) | (sel << 16);
+ e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8);
+ stl((uint8_t *)ptr, e1);
+ stl((uint8_t *)ptr + 4, e2);
+}
+
+uint64_t idt_table[256];
+
+/* only dpl matters as we do only user space emulation */
+static void set_idt(int n, unsigned int dpl)
+{
+ set_gate(idt_table + n, 0, dpl, 0, 0);
+}
+
+void qemu_free(void *ptr)
+{
+ free(ptr);
+}
+
+void *qemu_malloc(size_t size)
+{
+ return malloc(size);
+}
+
+void qemu_printf(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ vprintf(fmt, ap);
+ va_end(ap);
+}
+
+/* XXX: this is a bug in helper2.c */
+int errno;
+
+/**********************************************/
+
+#define COM_BASE_ADDR 0x10100
+
+void usage(void)
+{
+ printf("qruncom version 0.1 (c) 2003 Fabrice Bellard\n"
+ "usage: qruncom file.com\n"
+ "user mode libqemu demo: run simple .com DOS executables\n");
+ exit(1);
+}
+
+static inline uint8_t *seg_to_linear(unsigned int seg, unsigned int reg)
+{
+ return (uint8_t *)((seg << 4) + (reg & 0xffff));
+}
+
+static inline void pushw(CPUState *env, int val)
+{
+ env->regs[R_ESP] = (env->regs[R_ESP] & ~0xffff) | ((env->regs[R_ESP] - 2) & 0xffff);
+ *(uint16_t *)seg_to_linear(env->segs[R_SS].selector, env->regs[R_ESP]) = val;
+}
+
+static void host_segv_handler(int host_signum, siginfo_t *info,
+ void *puc)
+{
+ if (cpu_signal_handler(host_signum, info, puc)) {
+ return;
+ }
+ abort();
+}
+
+int main(int argc, char **argv)
+{
+ uint8_t *vm86_mem;
+ const char *filename;
+ int fd, ret, seg;
+ CPUState *env;
+
+ if (argc != 2)
+ usage();
+ filename = argv[1];
+
+ vm86_mem = mmap((void *)0x00000000, 0x110000,
+ PROT_WRITE | PROT_READ | PROT_EXEC,
+ MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0);
+ if (vm86_mem == MAP_FAILED) {
+ perror("mmap");
+ exit(1);
+ }
+
+ /* load the MSDOS .com executable */
+ fd = open(filename, O_RDONLY);
+ if (fd < 0) {
+ perror(filename);
+ exit(1);
+ }
+ ret = read(fd, vm86_mem + COM_BASE_ADDR, 65536 - 256);
+ if (ret < 0) {
+ perror("read");
+ exit(1);
+ }
+ close(fd);
+
+ /* install exception handler for CPU emulator */
+ {
+ struct sigaction act;
+
+ sigfillset(&act.sa_mask);
+ act.sa_flags = SA_SIGINFO;
+ // act.sa_flags |= SA_ONSTACK;
+
+ act.sa_sigaction = host_segv_handler;
+ sigaction(SIGSEGV, &act, NULL);
+ sigaction(SIGBUS, &act, NULL);
+#if defined (TARGET_I386) && defined(USE_CODE_COPY)
+ sigaction(SIGFPE, &act, NULL);
+#endif
+ }
+
+ // cpu_set_log(CPU_LOG_TB_IN_ASM | CPU_LOG_TB_OUT_ASM | CPU_LOG_EXEC);
+
+ env = cpu_init();
+
+ /* disable code copy to simplify debugging */
+ code_copy_enabled = 0;
+
+ /* set user mode state (XXX: should be done automatically by
+ cpu_init ?) */
+ env->user_mode_only = 1;
+
+ cpu_x86_set_cpl(env, 3);
+
+ env->cr[0] = CR0_PG_MASK | CR0_WP_MASK | CR0_PE_MASK;
+ /* NOTE: hflags duplicates some of the virtual CPU state */
+ env->hflags |= HF_PE_MASK | VM_MASK;
+
+ /* flags setup : we activate the IRQs by default as in user
+ mode. We also activate the VM86 flag to run DOS code */
+ env->eflags |= IF_MASK | VM_MASK;
+
+ /* init basic registers */
+ env->eip = 0x100;
+ env->regs[R_ESP] = 0xfffe;
+ seg = (COM_BASE_ADDR - 0x100) >> 4;
+
+ cpu_x86_load_seg_cache(env, R_CS, seg,
+ (uint8_t *)(seg << 4), 0xffff, 0);
+ cpu_x86_load_seg_cache(env, R_SS, seg,
+ (uint8_t *)(seg << 4), 0xffff, 0);
+ cpu_x86_load_seg_cache(env, R_DS, seg,
+ (uint8_t *)(seg << 4), 0xffff, 0);
+ cpu_x86_load_seg_cache(env, R_ES, seg,
+ (uint8_t *)(seg << 4), 0xffff, 0);
+ cpu_x86_load_seg_cache(env, R_FS, seg,
+ (uint8_t *)(seg << 4), 0xffff, 0);
+ cpu_x86_load_seg_cache(env, R_GS, seg,
+ (uint8_t *)(seg << 4), 0xffff, 0);
+
+ /* exception support */
+ env->idt.base = (void *)idt_table;
+ env->idt.limit = sizeof(idt_table) - 1;
+ set_idt(0, 0);
+ set_idt(1, 0);
+ set_idt(2, 0);
+ set_idt(3, 3);
+ set_idt(4, 3);
+ set_idt(5, 3);
+ set_idt(6, 0);
+ set_idt(7, 0);
+ set_idt(8, 0);
+ set_idt(9, 0);
+ set_idt(10, 0);
+ set_idt(11, 0);
+ set_idt(12, 0);
+ set_idt(13, 0);
+ set_idt(14, 0);
+ set_idt(15, 0);
+ set_idt(16, 0);
+ set_idt(17, 0);
+ set_idt(18, 0);
+ set_idt(19, 0);
+
+ /* put return code */
+ *seg_to_linear(env->segs[R_CS].selector, 0) = 0xb4; /* mov ah, $0 */
+ *seg_to_linear(env->segs[R_CS].selector, 1) = 0x00;
+ *seg_to_linear(env->segs[R_CS].selector, 2) = 0xcd; /* int $0x21 */
+ *seg_to_linear(env->segs[R_CS].selector, 3) = 0x21;
+ pushw(env, 0x0000);
+
+ /* the value of these registers seem to be assumed by pi_10.com */
+ env->regs[R_ESI] = 0x100;
+ env->regs[R_ECX] = 0xff;
+ env->regs[R_EBP] = 0x0900;
+ env->regs[R_EDI] = 0xfffe;
+
+ /* inform the emulator of the mmaped memory */
+ page_set_flags(0x00000000, 0x110000,
+ PAGE_WRITE | PAGE_READ | PAGE_EXEC | PAGE_VALID);
+
+ for(;;) {
+ ret = cpu_x86_exec(env);
+ switch(ret) {
+ case EXCP0D_GPF:
+ {
+ int int_num, ah;
+ int_num = *(env->segs[R_CS].base + env->eip + 1);
+ if (int_num != 0x21)
+ goto unknown_int;
+ ah = (env->regs[R_EAX] >> 8) & 0xff;
+ switch(ah) {
+ case 0x00: /* exit */
+ exit(0);
+ case 0x02: /* write char */
+ {
+ uint8_t c = env->regs[R_EDX];
+ write(1, &c, 1);
+ }
+ break;
+ case 0x09: /* write string */
+ {
+ uint8_t c;
+ for(;;) {
+ c = *seg_to_linear(env->segs[R_DS].selector, env->regs[R_EAX]);
+ if (c == '$')
+ break;
+ write(1, &c, 1);
+ }
+ env->regs[R_EAX] = (env->regs[R_EAX] & ~0xff) | '$';
+ }
+ break;
+ default:
+ unknown_int:
+ fprintf(stderr, "unsupported int 0x%02x\n", int_num);
+ cpu_dump_state(env, stderr, 0);
+ // exit(1);
+ }
+ env->eip += 2;
+ }
+ break;
+ default:
+ fprintf(stderr, "unhandled cpu_exec return code (0x%x)\n", ret);
+ cpu_dump_state(env, stderr, 0);
+ exit(1);
+ }
+ }
+}
--- /dev/null
+/*
+ * Simple example of use of vm86: launch a basic .com DOS executable
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/mman.h>
+#include <signal.h>
+
+#include <linux/unistd.h>
+#include <asm/vm86.h>
+
+//#define SIGTEST
+
+#undef __syscall_return
+#define __syscall_return(type, res) \
+do { \
+ return (type) (res); \
+} while (0)
+
+_syscall2(int, vm86, int, func, struct vm86plus_struct *, v86)
+
+#define COM_BASE_ADDR 0x10100
+
+void usage(void)
+{
+ printf("runcom version 0.1 (c) 2003 Fabrice Bellard\n"
+ "usage: runcom file.com\n"
+ "VM86 Run simple .com DOS executables (linux vm86 test mode)\n");
+ exit(1);
+}
+
+static inline void set_bit(uint8_t *a, unsigned int bit)
+{
+ a[bit / 8] |= (1 << (bit % 8));
+}
+
+static inline uint8_t *seg_to_linear(unsigned int seg, unsigned int reg)
+{
+ return (uint8_t *)((seg << 4) + (reg & 0xffff));
+}
+
+static inline void pushw(struct vm86_regs *r, int val)
+{
+ r->esp = (r->esp & ~0xffff) | ((r->esp - 2) & 0xffff);
+ *(uint16_t *)seg_to_linear(r->ss, r->esp) = val;
+}
+
+void dump_regs(struct vm86_regs *r)
+{
+ fprintf(stderr,
+ "EAX=%08lx EBX=%08lx ECX=%08lx EDX=%08lx\n"
+ "ESI=%08lx EDI=%08lx EBP=%08lx ESP=%08lx\n"
+ "EIP=%08lx EFL=%08lx\n"
+ "CS=%04x DS=%04x ES=%04x SS=%04x FS=%04x GS=%04x\n",
+ r->eax, r->ebx, r->ecx, r->edx, r->esi, r->edi, r->ebp, r->esp,
+ r->eip, r->eflags,
+ r->cs, r->ds, r->es, r->ss, r->fs, r->gs);
+}
+
+#ifdef SIGTEST
+void alarm_handler(int sig)
+{
+ fprintf(stderr, "alarm signal=%d\n", sig);
+ alarm(1);
+}
+#endif
+
+int main(int argc, char **argv)
+{
+ uint8_t *vm86_mem;
+ const char *filename;
+ int fd, ret, seg;
+ struct vm86plus_struct ctx;
+ struct vm86_regs *r;
+
+ if (argc != 2)
+ usage();
+ filename = argv[1];
+
+ vm86_mem = mmap((void *)0x00000000, 0x110000,
+ PROT_WRITE | PROT_READ | PROT_EXEC,
+ MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0);
+ if (vm86_mem == MAP_FAILED) {
+ perror("mmap");
+ exit(1);
+ }
+#ifdef SIGTEST
+ {
+ struct sigaction act;
+
+ act.sa_handler = alarm_handler;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+ sigaction(SIGALRM, &act, NULL);
+ alarm(1);
+ }
+#endif
+
+ /* load the MSDOS .com executable */
+ fd = open(filename, O_RDONLY);
+ if (fd < 0) {
+ perror(filename);
+ exit(1);
+ }
+ ret = read(fd, vm86_mem + COM_BASE_ADDR, 65536 - 256);
+ if (ret < 0) {
+ perror("read");
+ exit(1);
+ }
+ close(fd);
+
+ memset(&ctx, 0, sizeof(ctx));
+ /* init basic registers */
+ r = &ctx.regs;
+ r->eip = 0x100;
+ r->esp = 0xfffe;
+ seg = (COM_BASE_ADDR - 0x100) >> 4;
+ r->cs = seg;
+ r->ss = seg;
+ r->ds = seg;
+ r->es = seg;
+ r->fs = seg;
+ r->gs = seg;
+ r->eflags = VIF_MASK;
+
+ /* put return code */
+ set_bit((uint8_t *)&ctx.int_revectored, 0x21);
+ *seg_to_linear(r->cs, 0) = 0xb4; /* mov ah, $0 */
+ *seg_to_linear(r->cs, 1) = 0x00;
+ *seg_to_linear(r->cs, 2) = 0xcd; /* int $0x21 */
+ *seg_to_linear(r->cs, 3) = 0x21;
+ pushw(&ctx.regs, 0x0000);
+
+ /* the value of these registers seem to be assumed by pi_10.com */
+ r->esi = 0x100;
+ r->ecx = 0xff;
+ r->ebp = 0x0900;
+ r->edi = 0xfffe;
+
+ for(;;) {
+ ret = vm86(VM86_ENTER, &ctx);
+ switch(VM86_TYPE(ret)) {
+ case VM86_INTx:
+ {
+ int int_num, ah;
+
+ int_num = VM86_ARG(ret);
+ if (int_num != 0x21)
+ goto unknown_int;
+ ah = (r->eax >> 8) & 0xff;
+ switch(ah) {
+ case 0x00: /* exit */
+ exit(0);
+ case 0x02: /* write char */
+ {
+ uint8_t c = r->edx;
+ write(1, &c, 1);
+ }
+ break;
+ case 0x09: /* write string */
+ {
+ uint8_t c;
+ for(;;) {
+ c = *seg_to_linear(r->ds, r->edx);
+ if (c == '$')
+ break;
+ write(1, &c, 1);
+ }
+ r->eax = (r->eax & ~0xff) | '$';
+ }
+ break;
+ default:
+ unknown_int:
+ fprintf(stderr, "unsupported int 0x%02x\n", int_num);
+ dump_regs(&ctx.regs);
+ // exit(1);
+ }
+ }
+ break;
+ case VM86_SIGNAL:
+ /* a signal came, we just ignore that */
+ break;
+ case VM86_STI:
+ break;
+ default:
+ fprintf(stderr, "unhandled vm86 return code (0x%x)\n", ret);
+ dump_regs(&ctx.regs);
+ exit(1);
+ }
+ }
+}
--- /dev/null
+
+/* from valgrind tests */
+
+/* ================ sha1.c ================ */
+/*
+SHA-1 in C
+By Steve Reid <steve@edmweb.com>
+100% Public Domain
+
+Test Vectors (from FIPS PUB 180-1)
+"abc"
+ A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
+"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+ 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
+A million repetitions of "a"
+ 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
+*/
+
+/* #define LITTLE_ENDIAN * This should be #define'd already, if true. */
+/* #define SHA1HANDSOFF * Copies data before messing with it. */
+
+#define SHA1HANDSOFF
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h> /* for u_int*_t */
+
+/* ================ sha1.h ================ */
+/*
+SHA-1 in C
+By Steve Reid <steve@edmweb.com>
+100% Public Domain
+*/
+
+typedef struct {
+ u_int32_t state[5];
+ u_int32_t count[2];
+ unsigned char buffer[64];
+} SHA1_CTX;
+
+void SHA1Transform(u_int32_t state[5], const unsigned char buffer[64]);
+void SHA1Init(SHA1_CTX* context);
+void SHA1Update(SHA1_CTX* context, const unsigned char* data, u_int32_t len);
+void SHA1Final(unsigned char digest[20], SHA1_CTX* context);
+/* ================ end of sha1.h ================ */
+#include <endian.h>
+
+#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
+
+/* blk0() and blk() perform the initial expand. */
+/* I got the idea of expanding during the round function from SSLeay */
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
+ |(rol(block->l[i],8)&0x00FF00FF))
+#elif BYTE_ORDER == BIG_ENDIAN
+#define blk0(i) block->l[i]
+#else
+#error "Endianness not defined!"
+#endif
+#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
+ ^block->l[(i+2)&15]^block->l[i&15],1))
+
+/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
+#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
+#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
+#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
+#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
+
+
+/* Hash a single 512-bit block. This is the core of the algorithm. */
+
+void SHA1Transform(u_int32_t state[5], const unsigned char buffer[64])
+{
+u_int32_t a, b, c, d, e;
+typedef union {
+ unsigned char c[64];
+ u_int32_t l[16];
+} CHAR64LONG16;
+#ifdef SHA1HANDSOFF
+CHAR64LONG16 block[1]; /* use array to appear as a pointer */
+ memcpy(block, buffer, 64);
+#else
+ /* The following had better never be used because it causes the
+ * pointer-to-const buffer to be cast into a pointer to non-const.
+ * And the result is written through. I threw a "const" in, hoping
+ * this will cause a diagnostic.
+ */
+CHAR64LONG16* block = (const CHAR64LONG16*)buffer;
+#endif
+ /* Copy context->state[] to working vars */
+ a = state[0];
+ b = state[1];
+ c = state[2];
+ d = state[3];
+ e = state[4];
+ /* 4 rounds of 20 operations each. Loop unrolled. */
+ R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
+ R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
+ R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
+ R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
+ R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+ R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
+ R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
+ R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
+ R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
+ R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
+ R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
+ R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
+ R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
+ R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
+ R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
+ R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
+ R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
+ R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
+ R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
+ R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
+ /* Add the working vars back into context.state[] */
+ state[0] += a;
+ state[1] += b;
+ state[2] += c;
+ state[3] += d;
+ state[4] += e;
+ /* Wipe variables */
+ a = b = c = d = e = 0;
+#ifdef SHA1HANDSOFF
+ memset(block, '\0', sizeof(block));
+#endif
+}
+
+
+/* SHA1Init - Initialize new context */
+
+void SHA1Init(SHA1_CTX* context)
+{
+ /* SHA1 initialization constants */
+ context->state[0] = 0x67452301;
+ context->state[1] = 0xEFCDAB89;
+ context->state[2] = 0x98BADCFE;
+ context->state[3] = 0x10325476;
+ context->state[4] = 0xC3D2E1F0;
+ context->count[0] = context->count[1] = 0;
+}
+
+
+/* Run your data through this. */
+
+void SHA1Update(SHA1_CTX* context, const unsigned char* data, u_int32_t len)
+{
+u_int32_t i;
+u_int32_t j;
+
+ j = context->count[0];
+ if ((context->count[0] += len << 3) < j)
+ context->count[1]++;
+ context->count[1] += (len>>29);
+ j = (j >> 3) & 63;
+ if ((j + len) > 63) {
+ memcpy(&context->buffer[j], data, (i = 64-j));
+ SHA1Transform(context->state, context->buffer);
+ for ( ; i + 63 < len; i += 64) {
+ SHA1Transform(context->state, &data[i]);
+ }
+ j = 0;
+ }
+ else i = 0;
+ memcpy(&context->buffer[j], &data[i], len - i);
+}
+
+
+/* Add padding and return the message digest. */
+
+void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
+{
+unsigned i;
+unsigned char finalcount[8];
+unsigned char c;
+
+#if 0 /* untested "improvement" by DHR */
+ /* Convert context->count to a sequence of bytes
+ * in finalcount. Second element first, but
+ * big-endian order within element.
+ * But we do it all backwards.
+ */
+ unsigned char *fcp = &finalcount[8];
+
+ for (i = 0; i < 2; i++)
+ {
+ u_int32_t t = context->count[i];
+ int j;
+
+ for (j = 0; j < 4; t >>= 8, j++)
+ *--fcp = (unsigned char) t
+ }
+#else
+ for (i = 0; i < 8; i++) {
+ finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
+ >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
+ }
+#endif
+ c = 0200;
+ SHA1Update(context, &c, 1);
+ while ((context->count[0] & 504) != 448) {
+ c = 0000;
+ SHA1Update(context, &c, 1);
+ }
+ SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform() */
+ for (i = 0; i < 20; i++) {
+ digest[i] = (unsigned char)
+ ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
+ }
+ /* Wipe variables */
+ memset(context, '\0', sizeof(*context));
+ memset(&finalcount, '\0', sizeof(finalcount));
+}
+/* ================ end of sha1.c ================ */
+
+#define BUFSIZE 4096
+
+int
+main(int argc, char **argv)
+{
+ SHA1_CTX ctx;
+ unsigned char hash[20], buf[BUFSIZE];
+ int i;
+
+ for(i=0;i<BUFSIZE;i++)
+ buf[i] = i;
+
+ SHA1Init(&ctx);
+ for(i=0;i<1000;i++)
+ SHA1Update(&ctx, buf, BUFSIZE);
+ SHA1Final(hash, &ctx);
+
+ printf("SHA1=");
+ for(i=0;i<20;i++)
+ printf("%02x", hash[i]);
+ printf("\n");
+ return 0;
+}
+
+
--- /dev/null
+ .code16
+ .globl code16_start
+ .globl code16_end
+
+CS_SEG = 0xf
+
+code16_start:
+
+ .globl code16_func1
+
+ /* basic test */
+code16_func1 = . - code16_start
+ mov $1, %eax
+ data32 lret
+
+/* test push/pop in 16 bit mode */
+ .globl code16_func2
+code16_func2 = . - code16_start
+ xor %eax, %eax
+ mov $0x12345678, %ebx
+ movl %esp, %ecx
+ push %bx
+ subl %esp, %ecx
+ pop %ax
+ data32 lret
+
+/* test various jmp opcodes */
+ .globl code16_func3
+code16_func3 = . - code16_start
+ jmp 1f
+ nop
+1:
+ mov $4, %eax
+ mov $0x12345678, %ebx
+ xor %bx, %bx
+ jz 2f
+ add $2, %ax
+2:
+
+ call myfunc
+
+ lcall $CS_SEG, $(myfunc2 - code16_start)
+
+ ljmp $CS_SEG, $(myjmp1 - code16_start)
+myjmp1_next:
+
+ cs lcall myfunc2_addr - code16_start
+
+ cs ljmp myjmp2_addr - code16_start
+myjmp2_next:
+
+ data32 lret
+
+myfunc2_addr:
+ .short myfunc2 - code16_start
+ .short CS_SEG
+
+myjmp2_addr:
+ .short myjmp2 - code16_start
+ .short CS_SEG
+
+myjmp1:
+ add $8, %ax
+ jmp myjmp1_next
+
+myjmp2:
+ add $16, %ax
+ jmp myjmp2_next
+
+myfunc:
+ add $1, %ax
+ ret
+
+myfunc2:
+ add $4, %ax
+ lret
+
+
+code16_end:
+
+
+/* other 32 bits tests */
+ .code32
+
+ .globl func_lret32
+func_lret32:
+ movl $0x87654321, %eax
+ lret
+
+ .globl func_iret32
+func_iret32:
+ movl $0xabcd4321, %eax
+ iret
+
+
+
+
\ No newline at end of file
--- /dev/null
+
+void glue(glue(test_, OP), b)(int op0, int op1)
+{
+ int res, s1, s0, flags;
+ s0 = op0;
+ s1 = op1;
+ res = s0;
+ flags = 0;
+ asm ("push %4\n\t"
+ "popf\n\t"
+ stringify(OP)"b %b2\n\t"
+ "pushf\n\t"
+ "popl %1\n\t"
+ : "=a" (res), "=g" (flags)
+ : "q" (s1), "0" (res), "1" (flags));
+ printf("%-10s A=%08x B=%08x R=%08x CC=%04x\n",
+ stringify(OP) "b", s0, s1, res, flags & CC_MASK);
+}
+
+void glue(glue(test_, OP), w)(int op0h, int op0, int op1)
+{
+ int res, s1, flags, resh;
+ s1 = op1;
+ resh = op0h;
+ res = op0;
+ flags = 0;
+ asm ("push %5\n\t"
+ "popf\n\t"
+ stringify(OP) "w %w3\n\t"
+ "pushf\n\t"
+ "popl %1\n\t"
+ : "=a" (res), "=g" (flags), "=d" (resh)
+ : "q" (s1), "0" (res), "1" (flags), "2" (resh));
+ printf("%-10s AH=%08x AL=%08x B=%08x RH=%08x RL=%08x CC=%04x\n",
+ stringify(OP) "w", op0h, op0, s1, resh, res, flags & CC_MASK);
+}
+
+void glue(glue(test_, OP), l)(int op0h, int op0, int op1)
+{
+ int res, s1, flags, resh;
+ s1 = op1;
+ resh = op0h;
+ res = op0;
+ flags = 0;
+ asm ("push %5\n\t"
+ "popf\n\t"
+ stringify(OP) "l %3\n\t"
+ "pushf\n\t"
+ "popl %1\n\t"
+ : "=a" (res), "=g" (flags), "=d" (resh)
+ : "q" (s1), "0" (res), "1" (flags), "2" (resh));
+ printf("%-10s AH=%08x AL=%08x B=%08x RH=%08x RL=%08x CC=%04x\n",
+ stringify(OP) "l", op0h, op0, s1, resh, res, flags & CC_MASK);
+}
+
+#undef OP
--- /dev/null
+
+#define exec_op glue(exec_, OP)
+#define exec_opl glue(glue(exec_, OP), l)
+#define exec_opw glue(glue(exec_, OP), w)
+#define exec_opb glue(glue(exec_, OP), b)
+
+#ifndef OP_SHIFTD
+
+#ifdef OP_NOBYTE
+#define EXECSHIFT(size, res, s1, s2, flags) \
+ asm ("push %4\n\t"\
+ "popf\n\t"\
+ stringify(OP) size " %" size "2, %" size "0\n\t" \
+ "pushf\n\t"\
+ "popl %1\n\t"\
+ : "=g" (res), "=g" (flags)\
+ : "r" (s1), "0" (res), "1" (flags));
+#else
+#define EXECSHIFT(size, res, s1, s2, flags) \
+ asm ("push %4\n\t"\
+ "popf\n\t"\
+ stringify(OP) size " %%cl, %" size "0\n\t" \
+ "pushf\n\t"\
+ "popl %1\n\t"\
+ : "=q" (res), "=g" (flags)\
+ : "c" (s1), "0" (res), "1" (flags));
+#endif
+
+void exec_opl(int s2, int s0, int s1, int iflags)
+{
+ int res, flags;
+ res = s0;
+ flags = iflags;
+ EXECSHIFT("", res, s1, s2, flags);
+ /* overflow is undefined if count != 1 */
+ if (s1 != 1)
+ flags &= ~CC_O;
+ printf("%-10s A=%08x B=%08x R=%08x CCIN=%04x CC=%04x\n",
+ stringify(OP) "l", s0, s1, res, iflags, flags & CC_MASK);
+}
+
+void exec_opw(int s2, int s0, int s1, int iflags)
+{
+ int res, flags;
+ res = s0;
+ flags = iflags;
+ EXECSHIFT("w", res, s1, s2, flags);
+ /* overflow is undefined if count != 1 */
+ if (s1 != 1)
+ flags &= ~CC_O;
+ printf("%-10s A=%08x B=%08x R=%08x CCIN=%04x CC=%04x\n",
+ stringify(OP) "w", s0, s1, res, iflags, flags & CC_MASK);
+}
+
+#else
+#define EXECSHIFT(size, res, s1, s2, flags) \
+ asm ("push %4\n\t"\
+ "popf\n\t"\
+ stringify(OP) size " %%cl, %" size "5, %" size "0\n\t" \
+ "pushf\n\t"\
+ "popl %1\n\t"\
+ : "=g" (res), "=g" (flags)\
+ : "c" (s1), "0" (res), "1" (flags), "r" (s2));
+
+void exec_opl(int s2, int s0, int s1, int iflags)
+{
+ int res, flags;
+ res = s0;
+ flags = iflags;
+ EXECSHIFT("", res, s1, s2, flags);
+ /* overflow is undefined if count != 1 */
+ if (s1 != 1)
+ flags &= ~CC_O;
+ printf("%-10s A=%08x B=%08x C=%08x R=%08x CCIN=%04x CC=%04x\n",
+ stringify(OP) "l", s0, s2, s1, res, iflags, flags & CC_MASK);
+}
+
+void exec_opw(int s2, int s0, int s1, int iflags)
+{
+ int res, flags;
+ res = s0;
+ flags = iflags;
+ EXECSHIFT("w", res, s1, s2, flags);
+ /* overflow is undefined if count != 1 */
+ if (s1 != 1)
+ flags &= ~CC_O;
+ printf("%-10s A=%08x B=%08x C=%08x R=%08x CCIN=%04x CC=%04x\n",
+ stringify(OP) "w", s0, s2, s1, res, iflags, flags & CC_MASK);
+}
+
+#endif
+
+#ifndef OP_NOBYTE
+void exec_opb(int s0, int s1, int iflags)
+{
+ int res, flags;
+ res = s0;
+ flags = iflags;
+ EXECSHIFT("b", res, s1, 0, flags);
+ /* overflow is undefined if count != 1 */
+ if (s1 != 1)
+ flags &= ~CC_O;
+ printf("%-10s A=%08x B=%08x R=%08x CCIN=%04x CC=%04x\n",
+ stringify(OP) "b", s0, s1, res, iflags, flags & CC_MASK);
+}
+#endif
+
+void exec_op(int s2, int s0, int s1)
+{
+ exec_opl(s2, s0, s1, 0);
+#ifdef OP_SHIFTD
+ if (s1 <= 15)
+ exec_opw(s2, s0, s1, 0);
+#else
+ exec_opw(s2, s0, s1, 0);
+#endif
+#ifndef OP_NOBYTE
+ exec_opb(s0, s1, 0);
+#endif
+#ifdef OP_CC
+ exec_opl(s2, s0, s1, CC_C);
+ exec_opw(s2, s0, s1, CC_C);
+ exec_opb(s0, s1, CC_C);
+#endif
+}
+
+void glue(test_, OP)(void)
+{
+ int i;
+ for(i = 0; i < 32; i++)
+ exec_op(0x21ad3d34, 0x12345678, i);
+ for(i = 0; i < 32; i++)
+ exec_op(0x813f3421, 0x82345678, i);
+}
+
+void *glue(_test_, OP) __init_call = glue(test_, OP);
+
+#undef OP
+#undef OP_CC
+#undef OP_SHIFTD
+#undef OP_NOBYTE
+#undef EXECSHIFT
+
--- /dev/null
+ .code16
+ .globl vm86_code_start
+ .globl vm86_code_end
+
+#define GET_OFFSET(x) ((x) - vm86_code_start + 0x100)
+
+vm86_code_start:
+ movw $GET_OFFSET(hello_world), %dx
+ movb $0x09, %ah
+ int $0x21
+
+ /* prepare int 0x90 vector */
+ xorw %ax, %ax
+ movw %ax, %es
+ es movw $GET_OFFSET(int90_test), 0x90 * 4
+ es movw %cs, 0x90 * 4 + 2
+
+ /* launch int 0x90 */
+
+ int $0x90
+
+ /* test IF support */
+ movw $GET_OFFSET(IF_msg), %dx
+ movb $0x09, %ah
+ int $0x21
+
+ pushf
+ popw %dx
+ movb $0xff, %ah
+ int $0x21
+
+ cli
+ pushf
+ popw %dx
+ movb $0xff, %ah
+ int $0x21
+
+ sti
+ pushfl
+ popl %edx
+ movb $0xff, %ah
+ int $0x21
+
+#if 0
+ movw $GET_OFFSET(IF_msg1), %dx
+ movb $0x09, %ah
+ int $0x21
+
+ pushf
+ movw %sp, %bx
+ andw $~0x200, (%bx)
+ popf
+#else
+ cli
+#endif
+
+ pushf
+ popw %dx
+ movb $0xff, %ah
+ int $0x21
+
+ pushfl
+ movw %sp, %bx
+ orw $0x200, (%bx)
+ popfl
+
+ pushfl
+ popl %edx
+ movb $0xff, %ah
+ int $0x21
+
+ movb $0x00, %ah
+ int $0x21
+
+int90_test:
+ pushf
+ pop %dx
+ movb $0xff, %ah
+ int $0x21
+
+ movw %sp, %bx
+ movw 4(%bx), %dx
+ movb $0xff, %ah
+ int $0x21
+
+ movw $GET_OFFSET(int90_msg), %dx
+ movb $0x09, %ah
+ int $0x21
+ iret
+
+int90_msg:
+ .string "INT90 started\n$"
+
+hello_world:
+ .string "Hello VM86 world\n$"
+
+IF_msg:
+ .string "VM86 IF test\n$"
+
+IF_msg1:
+ .string "If you see a diff here, your Linux kernel is buggy, please update to 2.4.20 kernel\n$"
+
+vm86_code_end:
+
\ No newline at end of file
--- /dev/null
+/*
+ * x86 CPU test
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+#define _GNU_SOURCE
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <math.h>
+#include <signal.h>
+#include <setjmp.h>
+#include <errno.h>
+#include <sys/ucontext.h>
+#include <sys/mman.h>
+#include <asm/vm86.h>
+
+#define TEST_CMOV 0
+#define TEST_FCOMI 0
+//#define LINUX_VM86_IOPL_FIX
+//#define TEST_P4_FLAGS
+
+#define xglue(x, y) x ## y
+#define glue(x, y) xglue(x, y)
+#define stringify(s) tostring(s)
+#define tostring(s) #s
+
+#define CC_C 0x0001
+#define CC_P 0x0004
+#define CC_A 0x0010
+#define CC_Z 0x0040
+#define CC_S 0x0080
+#define CC_O 0x0800
+
+#define __init_call __attribute__ ((unused,__section__ (".initcall.init")))
+
+static void *call_start __init_call = NULL;
+
+#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)
+
+#define OP add
+#include "test-i386.h"
+
+#define OP sub
+#include "test-i386.h"
+
+#define OP xor
+#include "test-i386.h"
+
+#define OP and
+#include "test-i386.h"
+
+#define OP or
+#include "test-i386.h"
+
+#define OP cmp
+#include "test-i386.h"
+
+#define OP adc
+#define OP_CC
+#include "test-i386.h"
+
+#define OP sbb
+#define OP_CC
+#include "test-i386.h"
+
+#define OP inc
+#define OP_CC
+#define OP1
+#include "test-i386.h"
+
+#define OP dec
+#define OP_CC
+#define OP1
+#include "test-i386.h"
+
+#define OP neg
+#define OP_CC
+#define OP1
+#include "test-i386.h"
+
+#define OP not
+#define OP_CC
+#define OP1
+#include "test-i386.h"
+
+#undef CC_MASK
+#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O)
+
+#define OP shl
+#include "test-i386-shift.h"
+
+#define OP shr
+#include "test-i386-shift.h"
+
+#define OP sar
+#include "test-i386-shift.h"
+
+#define OP rol
+#include "test-i386-shift.h"
+
+#define OP ror
+#include "test-i386-shift.h"
+
+#define OP rcr
+#define OP_CC
+#include "test-i386-shift.h"
+
+#define OP rcl
+#define OP_CC
+#include "test-i386-shift.h"
+
+#define OP shld
+#define OP_SHIFTD
+#define OP_NOBYTE
+#include "test-i386-shift.h"
+
+#define OP shrd
+#define OP_SHIFTD
+#define OP_NOBYTE
+#include "test-i386-shift.h"
+
+/* XXX: should be more precise ? */
+#undef CC_MASK
+#define CC_MASK (CC_C)
+
+#define OP bt
+#define OP_NOBYTE
+#include "test-i386-shift.h"
+
+#define OP bts
+#define OP_NOBYTE
+#include "test-i386-shift.h"
+
+#define OP btr
+#define OP_NOBYTE
+#include "test-i386-shift.h"
+
+#define OP btc
+#define OP_NOBYTE
+#include "test-i386-shift.h"
+
+/* lea test (modrm support) */
+#define TEST_LEA(STR)\
+{\
+ asm("leal " STR ", %0"\
+ : "=r" (res)\
+ : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\
+ printf("lea %s = %08x\n", STR, res);\
+}
+
+#define TEST_LEA16(STR)\
+{\
+ asm(".code16 ; .byte 0x67 ; leal " STR ", %0 ; .code32"\
+ : "=wq" (res)\
+ : "a" (eax), "b" (ebx), "c" (ecx), "d" (edx), "S" (esi), "D" (edi));\
+ printf("lea %s = %08x\n", STR, res);\
+}
+
+
+void test_lea(void)
+{
+ int eax, ebx, ecx, edx, esi, edi, res;
+ eax = 0x0001;
+ ebx = 0x0002;
+ ecx = 0x0004;
+ edx = 0x0008;
+ esi = 0x0010;
+ edi = 0x0020;
+
+ TEST_LEA("0x4000");
+
+ TEST_LEA("(%%eax)");
+ TEST_LEA("(%%ebx)");
+ TEST_LEA("(%%ecx)");
+ TEST_LEA("(%%edx)");
+ TEST_LEA("(%%esi)");
+ TEST_LEA("(%%edi)");
+
+ TEST_LEA("0x40(%%eax)");
+ TEST_LEA("0x40(%%ebx)");
+ TEST_LEA("0x40(%%ecx)");
+ TEST_LEA("0x40(%%edx)");
+ TEST_LEA("0x40(%%esi)");
+ TEST_LEA("0x40(%%edi)");
+
+ TEST_LEA("0x4000(%%eax)");
+ TEST_LEA("0x4000(%%ebx)");
+ TEST_LEA("0x4000(%%ecx)");
+ TEST_LEA("0x4000(%%edx)");
+ TEST_LEA("0x4000(%%esi)");
+ TEST_LEA("0x4000(%%edi)");
+
+ TEST_LEA("(%%eax, %%ecx)");
+ TEST_LEA("(%%ebx, %%edx)");
+ TEST_LEA("(%%ecx, %%ecx)");
+ TEST_LEA("(%%edx, %%ecx)");
+ TEST_LEA("(%%esi, %%ecx)");
+ TEST_LEA("(%%edi, %%ecx)");
+
+ TEST_LEA("0x40(%%eax, %%ecx)");
+ TEST_LEA("0x4000(%%ebx, %%edx)");
+
+ TEST_LEA("(%%ecx, %%ecx, 2)");
+ TEST_LEA("(%%edx, %%ecx, 4)");
+ TEST_LEA("(%%esi, %%ecx, 8)");
+
+ TEST_LEA("(,%%eax, 2)");
+ TEST_LEA("(,%%ebx, 4)");
+ TEST_LEA("(,%%ecx, 8)");
+
+ TEST_LEA("0x40(,%%eax, 2)");
+ TEST_LEA("0x40(,%%ebx, 4)");
+ TEST_LEA("0x40(,%%ecx, 8)");
+
+
+ TEST_LEA("-10(%%ecx, %%ecx, 2)");
+ TEST_LEA("-10(%%edx, %%ecx, 4)");
+ TEST_LEA("-10(%%esi, %%ecx, 8)");
+
+ TEST_LEA("0x4000(%%ecx, %%ecx, 2)");
+ TEST_LEA("0x4000(%%edx, %%ecx, 4)");
+ TEST_LEA("0x4000(%%esi, %%ecx, 8)");
+
+ /* limited 16 bit addressing test */
+ TEST_LEA16("0x4000");
+ TEST_LEA16("(%%bx)");
+ TEST_LEA16("(%%si)");
+ TEST_LEA16("(%%di)");
+ TEST_LEA16("0x40(%%bx)");
+ TEST_LEA16("0x40(%%si)");
+ TEST_LEA16("0x40(%%di)");
+ TEST_LEA16("0x4000(%%bx)");
+ TEST_LEA16("0x4000(%%si)");
+ TEST_LEA16("(%%bx,%%si)");
+ TEST_LEA16("(%%bx,%%di)");
+ TEST_LEA16("0x40(%%bx,%%si)");
+ TEST_LEA16("0x40(%%bx,%%di)");
+ TEST_LEA16("0x4000(%%bx,%%si)");
+ TEST_LEA16("0x4000(%%bx,%%di)");
+}
+
+#define TEST_JCC(JCC, v1, v2)\
+{\
+ int res;\
+ asm("movl $1, %0\n\t"\
+ "cmpl %2, %1\n\t"\
+ "j" JCC " 1f\n\t"\
+ "movl $0, %0\n\t"\
+ "1:\n\t"\
+ : "=r" (res)\
+ : "r" (v1), "r" (v2));\
+ printf("%-10s %d\n", "j" JCC, res);\
+\
+ asm("movl $0, %0\n\t"\
+ "cmpl %2, %1\n\t"\
+ "set" JCC " %b0\n\t"\
+ : "=r" (res)\
+ : "r" (v1), "r" (v2));\
+ printf("%-10s %d\n", "set" JCC, res);\
+ if (TEST_CMOV) {\
+ asm("movl $0x12345678, %0\n\t"\
+ "cmpl %2, %1\n\t"\
+ "cmov" JCC "l %3, %0\n\t"\
+ : "=r" (res)\
+ : "r" (v1), "r" (v2), "m" (1));\
+ printf("%-10s R=0x%08x\n", "cmov" JCC "l", res);\
+ asm("movl $0x12345678, %0\n\t"\
+ "cmpl %2, %1\n\t"\
+ "cmov" JCC "w %w3, %w0\n\t"\
+ : "=r" (res)\
+ : "r" (v1), "r" (v2), "r" (1));\
+ printf("%-10s R=0x%08x\n", "cmov" JCC "w", res);\
+ } \
+}
+
+/* various jump tests */
+void test_jcc(void)
+{
+ TEST_JCC("ne", 1, 1);
+ TEST_JCC("ne", 1, 0);
+
+ TEST_JCC("e", 1, 1);
+ TEST_JCC("e", 1, 0);
+
+ TEST_JCC("l", 1, 1);
+ TEST_JCC("l", 1, 0);
+ TEST_JCC("l", 1, -1);
+
+ TEST_JCC("le", 1, 1);
+ TEST_JCC("le", 1, 0);
+ TEST_JCC("le", 1, -1);
+
+ TEST_JCC("ge", 1, 1);
+ TEST_JCC("ge", 1, 0);
+ TEST_JCC("ge", -1, 1);
+
+ TEST_JCC("g", 1, 1);
+ TEST_JCC("g", 1, 0);
+ TEST_JCC("g", 1, -1);
+
+ TEST_JCC("b", 1, 1);
+ TEST_JCC("b", 1, 0);
+ TEST_JCC("b", 1, -1);
+
+ TEST_JCC("be", 1, 1);
+ TEST_JCC("be", 1, 0);
+ TEST_JCC("be", 1, -1);
+
+ TEST_JCC("ae", 1, 1);
+ TEST_JCC("ae", 1, 0);
+ TEST_JCC("ae", 1, -1);
+
+ TEST_JCC("a", 1, 1);
+ TEST_JCC("a", 1, 0);
+ TEST_JCC("a", 1, -1);
+
+
+ TEST_JCC("p", 1, 1);
+ TEST_JCC("p", 1, 0);
+
+ TEST_JCC("np", 1, 1);
+ TEST_JCC("np", 1, 0);
+
+ TEST_JCC("o", 0x7fffffff, 0);
+ TEST_JCC("o", 0x7fffffff, -1);
+
+ TEST_JCC("no", 0x7fffffff, 0);
+ TEST_JCC("no", 0x7fffffff, -1);
+
+ TEST_JCC("s", 0, 1);
+ TEST_JCC("s", 0, -1);
+ TEST_JCC("s", 0, 0);
+
+ TEST_JCC("ns", 0, 1);
+ TEST_JCC("ns", 0, -1);
+ TEST_JCC("ns", 0, 0);
+}
+
+#undef CC_MASK
+#ifdef TEST_P4_FLAGS
+#define CC_MASK (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A)
+#else
+#define CC_MASK (CC_O | CC_C)
+#endif
+
+#define OP mul
+#include "test-i386-muldiv.h"
+
+#define OP imul
+#include "test-i386-muldiv.h"
+
+void test_imulw2(int op0, int op1)
+{
+ int res, s1, s0, flags;
+ s0 = op0;
+ s1 = op1;
+ res = s0;
+ flags = 0;
+ asm ("push %4\n\t"
+ "popf\n\t"
+ "imulw %w2, %w0\n\t"
+ "pushf\n\t"
+ "popl %1\n\t"
+ : "=q" (res), "=g" (flags)
+ : "q" (s1), "0" (res), "1" (flags));
+ printf("%-10s A=%08x B=%08x R=%08x CC=%04x\n",
+ "imulw", s0, s1, res, flags & CC_MASK);
+}
+
+void test_imull2(int op0, int op1)
+{
+ int res, s1, s0, flags;
+ s0 = op0;
+ s1 = op1;
+ res = s0;
+ flags = 0;
+ asm ("push %4\n\t"
+ "popf\n\t"
+ "imull %2, %0\n\t"
+ "pushf\n\t"
+ "popl %1\n\t"
+ : "=q" (res), "=g" (flags)
+ : "q" (s1), "0" (res), "1" (flags));
+ printf("%-10s A=%08x B=%08x R=%08x CC=%04x\n",
+ "imull", s0, s1, res, flags & CC_MASK);
+}
+
+#define TEST_IMUL_IM(size, size1, op0, op1)\
+{\
+ int res, flags;\
+ flags = 0;\
+ res = 0;\
+ asm ("push %3\n\t"\
+ "popf\n\t"\
+ "imul" size " $" #op0 ", %" size1 "2, %" size1 "0\n\t" \
+ "pushf\n\t"\
+ "popl %1\n\t"\
+ : "=r" (res), "=g" (flags)\
+ : "r" (op1), "1" (flags), "0" (res));\
+ printf("%-10s A=%08x B=%08x R=%08x CC=%04x\n",\
+ "imul" size, op0, op1, res, flags & CC_MASK);\
+}
+
+
+#undef CC_MASK
+#define CC_MASK (0)
+
+#define OP div
+#include "test-i386-muldiv.h"
+
+#define OP idiv
+#include "test-i386-muldiv.h"
+
+void test_mul(void)
+{
+ test_imulb(0x1234561d, 4);
+ test_imulb(3, -4);
+ test_imulb(0x80, 0x80);
+ test_imulb(0x10, 0x10);
+
+ test_imulw(0, 0x1234001d, 45);
+ test_imulw(0, 23, -45);
+ test_imulw(0, 0x8000, 0x8000);
+ test_imulw(0, 0x100, 0x100);
+
+ test_imull(0, 0x1234001d, 45);
+ test_imull(0, 23, -45);
+ test_imull(0, 0x80000000, 0x80000000);
+ test_imull(0, 0x10000, 0x10000);
+
+ test_mulb(0x1234561d, 4);
+ test_mulb(3, -4);
+ test_mulb(0x80, 0x80);
+ test_mulb(0x10, 0x10);
+
+ test_mulw(0, 0x1234001d, 45);
+ test_mulw(0, 23, -45);
+ test_mulw(0, 0x8000, 0x8000);
+ test_mulw(0, 0x100, 0x100);
+
+ test_mull(0, 0x1234001d, 45);
+ test_mull(0, 23, -45);
+ test_mull(0, 0x80000000, 0x80000000);
+ test_mull(0, 0x10000, 0x10000);
+
+ test_imulw2(0x1234001d, 45);
+ test_imulw2(23, -45);
+ test_imulw2(0x8000, 0x8000);
+ test_imulw2(0x100, 0x100);
+
+ test_imull2(0x1234001d, 45);
+ test_imull2(23, -45);
+ test_imull2(0x80000000, 0x80000000);
+ test_imull2(0x10000, 0x10000);
+
+ TEST_IMUL_IM("w", "w", 45, 0x1234);
+ TEST_IMUL_IM("w", "w", -45, 23);
+ TEST_IMUL_IM("w", "w", 0x8000, 0x80000000);
+ TEST_IMUL_IM("w", "w", 0x7fff, 0x1000);
+
+ TEST_IMUL_IM("l", "", 45, 0x1234);
+ TEST_IMUL_IM("l", "", -45, 23);
+ TEST_IMUL_IM("l", "", 0x8000, 0x80000000);
+ TEST_IMUL_IM("l", "", 0x7fff, 0x1000);
+
+ test_idivb(0x12341678, 0x127e);
+ test_idivb(0x43210123, -5);
+ test_idivb(0x12340004, -1);
+
+ test_idivw(0, 0x12345678, 12347);
+ test_idivw(0, -23223, -45);
+ test_idivw(0, 0x12348000, -1);
+ test_idivw(0x12343, 0x12345678, 0x81238567);
+
+ test_idivl(0, 0x12345678, 12347);
+ test_idivl(0, -233223, -45);
+ test_idivl(0, 0x80000000, -1);
+ test_idivl(0x12343, 0x12345678, 0x81234567);
+
+ test_divb(0x12341678, 0x127e);
+ test_divb(0x43210123, -5);
+ test_divb(0x12340004, -1);
+
+ test_divw(0, 0x12345678, 12347);
+ test_divw(0, -23223, -45);
+ test_divw(0, 0x12348000, -1);
+ test_divw(0x12343, 0x12345678, 0x81238567);
+
+ test_divl(0, 0x12345678, 12347);
+ test_divl(0, -233223, -45);
+ test_divl(0, 0x80000000, -1);
+ test_divl(0x12343, 0x12345678, 0x81234567);
+}
+
+#define TEST_BSX(op, size, op0)\
+{\
+ int res, val, resz;\
+ val = op0;\
+ asm("xorl %1, %1\n"\
+ "movl $0x12345678, %0\n"\
+ #op " %" size "2, %" size "0 ; setz %b1" \
+ : "=r" (res), "=q" (resz)\
+ : "g" (val));\
+ printf("%-10s A=%08x R=%08x %d\n", #op, val, res, resz);\
+}
+
+void test_bsx(void)
+{
+ TEST_BSX(bsrw, "w", 0);
+ TEST_BSX(bsrw, "w", 0x12340128);
+ TEST_BSX(bsrl, "", 0);
+ TEST_BSX(bsrl, "", 0x00340128);
+ TEST_BSX(bsfw, "w", 0);
+ TEST_BSX(bsfw, "w", 0x12340128);
+ TEST_BSX(bsfl, "", 0);
+ TEST_BSX(bsfl, "", 0x00340128);
+}
+
+/**********************************************/
+
+void test_fops(double a, double b)
+{
+ printf("a=%f b=%f a+b=%f\n", a, b, a + b);
+ printf("a=%f b=%f a-b=%f\n", a, b, a - b);
+ printf("a=%f b=%f a*b=%f\n", a, b, a * b);
+ printf("a=%f b=%f a/b=%f\n", a, b, a / b);
+ printf("a=%f b=%f fmod(a, b)=%f\n", a, b, fmod(a, b));
+ printf("a=%f sqrt(a)=%f\n", a, sqrt(a));
+ printf("a=%f sin(a)=%f\n", a, sin(a));
+ printf("a=%f cos(a)=%f\n", a, cos(a));
+ printf("a=%f tan(a)=%f\n", a, tan(a));
+ printf("a=%f log(a)=%f\n", a, log(a));
+ printf("a=%f exp(a)=%f\n", a, exp(a));
+ printf("a=%f b=%f atan2(a, b)=%f\n", a, b, atan2(a, b));
+ /* just to test some op combining */
+ printf("a=%f asin(sin(a))=%f\n", a, asin(sin(a)));
+ printf("a=%f acos(cos(a))=%f\n", a, acos(cos(a)));
+ printf("a=%f atan(tan(a))=%f\n", a, atan(tan(a)));
+
+}
+
+void test_fcmp(double a, double b)
+{
+ printf("(%f<%f)=%d\n",
+ a, b, a < b);
+ printf("(%f<=%f)=%d\n",
+ a, b, a <= b);
+ printf("(%f==%f)=%d\n",
+ a, b, a == b);
+ printf("(%f>%f)=%d\n",
+ a, b, a > b);
+ printf("(%f<=%f)=%d\n",
+ a, b, a >= b);
+ if (TEST_FCOMI) {
+ unsigned int eflags;
+ /* test f(u)comi instruction */
+ asm("fcomi %2, %1\n"
+ "pushf\n"
+ "pop %0\n"
+ : "=r" (eflags)
+ : "t" (a), "u" (b));
+ printf("fcomi(%f %f)=%08x\n", a, b, eflags & (CC_Z | CC_P | CC_C));
+ }
+}
+
+void test_fcvt(double a)
+{
+ float fa;
+ long double la;
+ int16_t fpuc;
+ int i;
+ int64_t lla;
+ int ia;
+ int16_t wa;
+ double ra;
+
+ fa = a;
+ la = a;
+ printf("(float)%f = %f\n", a, fa);
+ printf("(long double)%f = %Lf\n", a, la);
+ printf("a=%016Lx\n", *(long long *)&a);
+ printf("la=%016Lx %04x\n", *(long long *)&la,
+ *(unsigned short *)((char *)(&la) + 8));
+
+ /* test all roundings */
+ asm volatile ("fstcw %0" : "=m" (fpuc));
+ for(i=0;i<4;i++) {
+ asm volatile ("fldcw %0" : : "m" ((fpuc & ~0x0c00) | (i << 10)));
+ asm volatile ("fist %0" : "=m" (wa) : "t" (a));
+ asm volatile ("fistl %0" : "=m" (ia) : "t" (a));
+ asm volatile ("fistpll %0" : "=m" (lla) : "t" (a) : "st");
+ asm volatile ("frndint ; fstl %0" : "=m" (ra) : "t" (a));
+ asm volatile ("fldcw %0" : : "m" (fpuc));
+ printf("(short)a = %d\n", wa);
+ printf("(int)a = %d\n", ia);
+ printf("(int64_t)a = %Ld\n", lla);
+ printf("rint(a) = %f\n", ra);
+ }
+}
+
+#define TEST(N) \
+ asm("fld" #N : "=t" (a)); \
+ printf("fld" #N "= %f\n", a);
+
+void test_fconst(void)
+{
+ double a;
+ TEST(1);
+ TEST(l2t);
+ TEST(l2e);
+ TEST(pi);
+ TEST(lg2);
+ TEST(ln2);
+ TEST(z);
+}
+
+void test_fbcd(double a)
+{
+ unsigned short bcd[5];
+ double b;
+
+ asm("fbstp %0" : "=m" (bcd[0]) : "t" (a) : "st");
+ asm("fbld %1" : "=t" (b) : "m" (bcd[0]));
+ printf("a=%f bcd=%04x%04x%04x%04x%04x b=%f\n",
+ a, bcd[4], bcd[3], bcd[2], bcd[1], bcd[0], b);
+}
+
+#define TEST_ENV(env, save, restore)\
+{\
+ memset((env), 0xaa, sizeof(*(env)));\
+ for(i=0;i<5;i++)\
+ asm volatile ("fldl %0" : : "m" (dtab[i]));\
+ asm(save " %0\n" : : "m" (*(env)));\
+ asm(restore " %0\n": : "m" (*(env)));\
+ for(i=0;i<5;i++)\
+ asm volatile ("fstpl %0" : "=m" (rtab[i]));\
+ for(i=0;i<5;i++)\
+ printf("res[%d]=%f\n", i, rtab[i]);\
+ printf("fpuc=%04x fpus=%04x fptag=%04x\n",\
+ (env)->fpuc,\
+ (env)->fpus & 0xff00,\
+ (env)->fptag);\
+}
+
+void test_fenv(void)
+{
+ struct __attribute__((packed)) {
+ uint16_t fpuc;
+ uint16_t dummy1;
+ uint16_t fpus;
+ uint16_t dummy2;
+ uint16_t fptag;
+ uint16_t dummy3;
+ uint32_t ignored[4];
+ long double fpregs[8];
+ } float_env32;
+ struct __attribute__((packed)) {
+ uint16_t fpuc;
+ uint16_t fpus;
+ uint16_t fptag;
+ uint16_t ignored[4];
+ long double fpregs[8];
+ } float_env16;
+ double dtab[8];
+ double rtab[8];
+ int i;
+
+ for(i=0;i<8;i++)
+ dtab[i] = i + 1;
+
+ TEST_ENV(&float_env16, "data16 fnstenv", "data16 fldenv");
+ TEST_ENV(&float_env16, "data16 fnsave", "data16 frstor");
+ TEST_ENV(&float_env32, "fnstenv", "fldenv");
+ TEST_ENV(&float_env32, "fnsave", "frstor");
+
+ /* test for ffree */
+ for(i=0;i<5;i++)
+ asm volatile ("fldl %0" : : "m" (dtab[i]));
+ asm volatile("ffree %st(2)");
+ asm volatile ("fnstenv %0\n" : : "m" (float_env32));
+ asm volatile ("fninit");
+ printf("fptag=%04x\n", float_env32.fptag);
+}
+
+
+#define TEST_FCMOV(a, b, eflags, CC)\
+{\
+ double res;\
+ asm("push %3\n"\
+ "popf\n"\
+ "fcmov" CC " %2, %0\n"\
+ : "=t" (res)\
+ : "0" (a), "u" (b), "g" (eflags));\
+ printf("fcmov%s eflags=0x%04x-> %f\n", \
+ CC, eflags, res);\
+}
+
+void test_fcmov(void)
+{
+ double a, b;
+ int eflags, i;
+
+ a = 1.0;
+ b = 2.0;
+ for(i = 0; i < 4; i++) {
+ eflags = 0;
+ if (i & 1)
+ eflags |= CC_C;
+ if (i & 2)
+ eflags |= CC_Z;
+ TEST_FCMOV(a, b, eflags, "b");
+ TEST_FCMOV(a, b, eflags, "e");
+ TEST_FCMOV(a, b, eflags, "be");
+ TEST_FCMOV(a, b, eflags, "nb");
+ TEST_FCMOV(a, b, eflags, "ne");
+ TEST_FCMOV(a, b, eflags, "nbe");
+ }
+ TEST_FCMOV(a, b, 0, "u");
+ TEST_FCMOV(a, b, CC_P, "u");
+ TEST_FCMOV(a, b, 0, "nu");
+ TEST_FCMOV(a, b, CC_P, "nu");
+}
+
+void test_floats(void)
+{
+ test_fops(2, 3);
+ test_fops(1.4, -5);
+ test_fcmp(2, -1);
+ test_fcmp(2, 2);
+ test_fcmp(2, 3);
+ test_fcvt(0.5);
+ test_fcvt(-0.5);
+ test_fcvt(1.0/7.0);
+ test_fcvt(-1.0/9.0);
+ test_fcvt(32768);
+ test_fcvt(-1e20);
+ test_fconst();
+ test_fbcd(1234567890123456);
+ test_fbcd(-123451234567890);
+ test_fenv();
+ if (TEST_CMOV) {
+ test_fcmov();
+ }
+}
+
+/**********************************************/
+
+#define TEST_BCD(op, op0, cc_in, cc_mask)\
+{\
+ int res, flags;\
+ res = op0;\
+ flags = cc_in;\
+ asm ("push %3\n\t"\
+ "popf\n\t"\
+ #op "\n\t"\
+ "pushf\n\t"\
+ "popl %1\n\t"\
+ : "=a" (res), "=g" (flags)\
+ : "0" (res), "1" (flags));\
+ printf("%-10s A=%08x R=%08x CCIN=%04x CC=%04x\n",\
+ #op, op0, res, cc_in, flags & cc_mask);\
+}
+
+void test_bcd(void)
+{
+ TEST_BCD(daa, 0x12340503, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(daa, 0x12340506, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(daa, 0x12340507, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(daa, 0x12340559, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(daa, 0x12340560, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(daa, 0x1234059f, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(daa, 0x123405a0, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(daa, 0x12340503, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(daa, 0x12340506, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(daa, 0x12340503, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(daa, 0x12340506, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(daa, 0x12340503, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(daa, 0x12340506, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+
+ TEST_BCD(das, 0x12340503, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(das, 0x12340506, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(das, 0x12340507, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(das, 0x12340559, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(das, 0x12340560, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(das, 0x1234059f, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(das, 0x123405a0, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(das, 0x12340503, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(das, 0x12340506, 0, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(das, 0x12340503, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(das, 0x12340506, CC_C, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(das, 0x12340503, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+ TEST_BCD(das, 0x12340506, CC_C | CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_A));
+
+ TEST_BCD(aaa, 0x12340205, CC_A, (CC_C | CC_A));
+ TEST_BCD(aaa, 0x12340306, CC_A, (CC_C | CC_A));
+ TEST_BCD(aaa, 0x1234040a, CC_A, (CC_C | CC_A));
+ TEST_BCD(aaa, 0x123405fa, CC_A, (CC_C | CC_A));
+ TEST_BCD(aaa, 0x12340205, 0, (CC_C | CC_A));
+ TEST_BCD(aaa, 0x12340306, 0, (CC_C | CC_A));
+ TEST_BCD(aaa, 0x1234040a, 0, (CC_C | CC_A));
+ TEST_BCD(aaa, 0x123405fa, 0, (CC_C | CC_A));
+
+ TEST_BCD(aas, 0x12340205, CC_A, (CC_C | CC_A));
+ TEST_BCD(aas, 0x12340306, CC_A, (CC_C | CC_A));
+ TEST_BCD(aas, 0x1234040a, CC_A, (CC_C | CC_A));
+ TEST_BCD(aas, 0x123405fa, CC_A, (CC_C | CC_A));
+ TEST_BCD(aas, 0x12340205, 0, (CC_C | CC_A));
+ TEST_BCD(aas, 0x12340306, 0, (CC_C | CC_A));
+ TEST_BCD(aas, 0x1234040a, 0, (CC_C | CC_A));
+ TEST_BCD(aas, 0x123405fa, 0, (CC_C | CC_A));
+
+ TEST_BCD(aam, 0x12340547, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));
+ TEST_BCD(aad, 0x12340407, CC_A, (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));
+}
+
+#define TEST_XCHG(op, size, opconst)\
+{\
+ int op0, op1;\
+ op0 = 0x12345678;\
+ op1 = 0xfbca7654;\
+ asm(#op " %" size "0, %" size "1" \
+ : "=q" (op0), opconst (op1) \
+ : "0" (op0), "1" (op1));\
+ printf("%-10s A=%08x B=%08x\n",\
+ #op, op0, op1);\
+}
+
+#define TEST_CMPXCHG(op, size, opconst, eax)\
+{\
+ int op0, op1;\
+ op0 = 0x12345678;\
+ op1 = 0xfbca7654;\
+ asm(#op " %" size "0, %" size "1" \
+ : "=q" (op0), opconst (op1) \
+ : "0" (op0), "1" (op1), "a" (eax));\
+ printf("%-10s EAX=%08x A=%08x C=%08x\n",\
+ #op, eax, op0, op1);\
+}
+
+void test_xchg(void)
+{
+ TEST_XCHG(xchgl, "", "=q");
+ TEST_XCHG(xchgw, "w", "=q");
+ TEST_XCHG(xchgb, "b", "=q");
+
+ TEST_XCHG(xchgl, "", "=m");
+ TEST_XCHG(xchgw, "w", "=m");
+ TEST_XCHG(xchgb, "b", "=m");
+
+ TEST_XCHG(xaddl, "", "=q");
+ TEST_XCHG(xaddw, "w", "=q");
+ TEST_XCHG(xaddb, "b", "=q");
+
+ {
+ int res;
+ res = 0x12345678;
+ asm("xaddl %1, %0" : "=r" (res) : "0" (res));
+ printf("xaddl same res=%08x\n", res);
+ }
+
+ TEST_XCHG(xaddl, "", "=m");
+ TEST_XCHG(xaddw, "w", "=m");
+ TEST_XCHG(xaddb, "b", "=m");
+
+ TEST_CMPXCHG(cmpxchgl, "", "=q", 0xfbca7654);
+ TEST_CMPXCHG(cmpxchgw, "w", "=q", 0xfbca7654);
+ TEST_CMPXCHG(cmpxchgb, "b", "=q", 0xfbca7654);
+
+ TEST_CMPXCHG(cmpxchgl, "", "=q", 0xfffefdfc);
+ TEST_CMPXCHG(cmpxchgw, "w", "=q", 0xfffefdfc);
+ TEST_CMPXCHG(cmpxchgb, "b", "=q", 0xfffefdfc);
+
+ TEST_CMPXCHG(cmpxchgl, "", "=m", 0xfbca7654);
+ TEST_CMPXCHG(cmpxchgw, "w", "=m", 0xfbca7654);
+ TEST_CMPXCHG(cmpxchgb, "b", "=m", 0xfbca7654);
+
+ TEST_CMPXCHG(cmpxchgl, "", "=m", 0xfffefdfc);
+ TEST_CMPXCHG(cmpxchgw, "w", "=m", 0xfffefdfc);
+ TEST_CMPXCHG(cmpxchgb, "b", "=m", 0xfffefdfc);
+
+ {
+ uint64_t op0, op1, op2;
+ int i, eflags;
+
+ for(i = 0; i < 2; i++) {
+ op0 = 0x123456789abcd;
+ if (i == 0)
+ op1 = 0xfbca765423456;
+ else
+ op1 = op0;
+ op2 = 0x6532432432434;
+ asm("cmpxchg8b %1\n"
+ "pushf\n"
+ "popl %2\n"
+ : "=A" (op0), "=m" (op1), "=g" (eflags)
+ : "0" (op0), "m" (op1), "b" ((int)op2), "c" ((int)(op2 >> 32)));
+ printf("cmpxchg8b: op0=%016llx op1=%016llx CC=%02x\n",
+ op0, op1, eflags & CC_Z);
+ }
+ }
+}
+
+/**********************************************/
+/* segmentation tests */
+
+#include <asm/ldt.h>
+#include <linux/unistd.h>
+#include <linux/version.h>
+
+_syscall3(int, modify_ldt, int, func, void *, ptr, unsigned long, bytecount)
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 5, 66)
+#define modify_ldt_ldt_s user_desc
+#endif
+
+uint8_t seg_data1[4096];
+uint8_t seg_data2[4096];
+
+#define MK_SEL(n) (((n) << 3) | 7)
+
+#define TEST_LR(op, size, seg, mask)\
+{\
+ int res, res2;\
+ res = 0x12345678;\
+ asm (op " %" size "2, %" size "0\n" \
+ "movl $0, %1\n"\
+ "jnz 1f\n"\
+ "movl $1, %1\n"\
+ "1:\n"\
+ : "=r" (res), "=r" (res2) : "m" (seg), "0" (res));\
+ printf(op ": Z=%d %08x\n", res2, res & ~(mask));\
+}
+
+/* NOTE: we use Linux modify_ldt syscall */
+void test_segs(void)
+{
+ struct modify_ldt_ldt_s ldt;
+ long long ldt_table[3];
+ int res, res2;
+ char tmp;
+ struct {
+ uint32_t offset;
+ uint16_t seg;
+ } __attribute__((packed)) segoff;
+
+ ldt.entry_number = 1;
+ ldt.base_addr = (unsigned long)&seg_data1;
+ ldt.limit = (sizeof(seg_data1) + 0xfff) >> 12;
+ ldt.seg_32bit = 1;
+ ldt.contents = MODIFY_LDT_CONTENTS_DATA;
+ ldt.read_exec_only = 0;
+ ldt.limit_in_pages = 1;
+ ldt.seg_not_present = 0;
+ ldt.useable = 1;
+ modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
+
+ ldt.entry_number = 2;
+ ldt.base_addr = (unsigned long)&seg_data2;
+ ldt.limit = (sizeof(seg_data2) + 0xfff) >> 12;
+ ldt.seg_32bit = 1;
+ ldt.contents = MODIFY_LDT_CONTENTS_DATA;
+ ldt.read_exec_only = 0;
+ ldt.limit_in_pages = 1;
+ ldt.seg_not_present = 0;
+ ldt.useable = 1;
+ modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
+
+ modify_ldt(0, &ldt_table, sizeof(ldt_table)); /* read ldt entries */
+#if 0
+ {
+ int i;
+ for(i=0;i<3;i++)
+ printf("%d: %016Lx\n", i, ldt_table[i]);
+ }
+#endif
+ /* do some tests with fs or gs */
+ asm volatile ("movl %0, %%fs" : : "r" (MK_SEL(1)));
+
+ seg_data1[1] = 0xaa;
+ seg_data2[1] = 0x55;
+
+ asm volatile ("fs movzbl 0x1, %0" : "=r" (res));
+ printf("FS[1] = %02x\n", res);
+
+ asm volatile ("pushl %%gs\n"
+ "movl %1, %%gs\n"
+ "gs movzbl 0x1, %0\n"
+ "popl %%gs\n"
+ : "=r" (res)
+ : "r" (MK_SEL(2)));
+ printf("GS[1] = %02x\n", res);
+
+ /* tests with ds/ss (implicit segment case) */
+ tmp = 0xa5;
+ asm volatile ("pushl %%ebp\n\t"
+ "pushl %%ds\n\t"
+ "movl %2, %%ds\n\t"
+ "movl %3, %%ebp\n\t"
+ "movzbl 0x1, %0\n\t"
+ "movzbl (%%ebp), %1\n\t"
+ "popl %%ds\n\t"
+ "popl %%ebp\n\t"
+ : "=r" (res), "=r" (res2)
+ : "r" (MK_SEL(1)), "r" (&tmp));
+ printf("DS[1] = %02x\n", res);
+ printf("SS[tmp] = %02x\n", res2);
+
+ segoff.seg = MK_SEL(2);
+ segoff.offset = 0xabcdef12;
+ asm volatile("lfs %2, %0\n\t"
+ "movl %%fs, %1\n\t"
+ : "=r" (res), "=g" (res2)
+ : "m" (segoff));
+ printf("FS:reg = %04x:%08x\n", res2, res);
+
+ TEST_LR("larw", "w", MK_SEL(2), 0x0100);
+ TEST_LR("larl", "", MK_SEL(2), 0x0100);
+ TEST_LR("lslw", "w", MK_SEL(2), 0);
+ TEST_LR("lsll", "", MK_SEL(2), 0);
+
+ TEST_LR("larw", "w", 0xfff8, 0);
+ TEST_LR("larl", "", 0xfff8, 0);
+ TEST_LR("lslw", "w", 0xfff8, 0);
+ TEST_LR("lsll", "", 0xfff8, 0);
+}
+
+/* 16 bit code test */
+extern char code16_start, code16_end;
+extern char code16_func1;
+extern char code16_func2;
+extern char code16_func3;
+
+void test_code16(void)
+{
+ struct modify_ldt_ldt_s ldt;
+ int res, res2;
+
+ /* build a code segment */
+ ldt.entry_number = 1;
+ ldt.base_addr = (unsigned long)&code16_start;
+ ldt.limit = &code16_end - &code16_start;
+ ldt.seg_32bit = 0;
+ ldt.contents = MODIFY_LDT_CONTENTS_CODE;
+ ldt.read_exec_only = 0;
+ ldt.limit_in_pages = 0;
+ ldt.seg_not_present = 0;
+ ldt.useable = 1;
+ modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
+
+ /* call the first function */
+ asm volatile ("lcall %1, %2"
+ : "=a" (res)
+ : "i" (MK_SEL(1)), "i" (&code16_func1): "memory", "cc");
+ printf("func1() = 0x%08x\n", res);
+ asm volatile ("lcall %2, %3"
+ : "=a" (res), "=c" (res2)
+ : "i" (MK_SEL(1)), "i" (&code16_func2): "memory", "cc");
+ printf("func2() = 0x%08x spdec=%d\n", res, res2);
+ asm volatile ("lcall %1, %2"
+ : "=a" (res)
+ : "i" (MK_SEL(1)), "i" (&code16_func3): "memory", "cc");
+ printf("func3() = 0x%08x\n", res);
+}
+
+extern char func_lret32;
+extern char func_iret32;
+
+void test_misc(void)
+{
+ char table[256];
+ int res, i;
+
+ for(i=0;i<256;i++) table[i] = 256 - i;
+ res = 0x12345678;
+ asm ("xlat" : "=a" (res) : "b" (table), "0" (res));
+ printf("xlat: EAX=%08x\n", res);
+
+ asm volatile ("pushl %%cs ; call %1"
+ : "=a" (res)
+ : "m" (func_lret32): "memory", "cc");
+ printf("func_lret32=%x\n", res);
+
+ asm volatile ("pushfl ; pushl %%cs ; call %1"
+ : "=a" (res)
+ : "m" (func_iret32): "memory", "cc");
+ printf("func_iret32=%x\n", res);
+
+ /* specific popl test */
+ asm volatile ("pushl $12345432 ; pushl $0x9abcdef ; popl (%%esp) ; popl %0"
+ : "=g" (res));
+ printf("popl esp=%x\n", res);
+
+ /* specific popw test */
+ asm volatile ("pushl $12345432 ; pushl $0x9abcdef ; popw (%%esp) ; addl $2, %%esp ; popl %0"
+ : "=g" (res));
+ printf("popw esp=%x\n", res);
+}
+
+uint8_t str_buffer[4096];
+
+#define TEST_STRING1(OP, size, DF, REP)\
+{\
+ int esi, edi, eax, ecx, eflags;\
+\
+ esi = (long)(str_buffer + sizeof(str_buffer) / 2);\
+ edi = (long)(str_buffer + sizeof(str_buffer) / 2) + 16;\
+ eax = 0x12345678;\
+ ecx = 17;\
+\
+ asm volatile ("pushl $0\n\t"\
+ "popf\n\t"\
+ DF "\n\t"\
+ REP #OP size "\n\t"\
+ "cld\n\t"\
+ "pushf\n\t"\
+ "popl %4\n\t"\
+ : "=S" (esi), "=D" (edi), "=a" (eax), "=c" (ecx), "=g" (eflags)\
+ : "0" (esi), "1" (edi), "2" (eax), "3" (ecx));\
+ printf("%-10s ESI=%08x EDI=%08x EAX=%08x ECX=%08x EFL=%04x\n",\
+ REP #OP size, esi, edi, eax, ecx,\
+ eflags & (CC_C | CC_P | CC_Z | CC_S | CC_O | CC_A));\
+}
+
+#define TEST_STRING(OP, REP)\
+ TEST_STRING1(OP, "b", "", REP);\
+ TEST_STRING1(OP, "w", "", REP);\
+ TEST_STRING1(OP, "l", "", REP);\
+ TEST_STRING1(OP, "b", "std", REP);\
+ TEST_STRING1(OP, "w", "std", REP);\
+ TEST_STRING1(OP, "l", "std", REP)
+
+void test_string(void)
+{
+ int i;
+ for(i = 0;i < sizeof(str_buffer); i++)
+ str_buffer[i] = i + 0x56;
+ TEST_STRING(stos, "");
+ TEST_STRING(stos, "rep ");
+ TEST_STRING(lods, ""); /* to verify stos */
+ TEST_STRING(lods, "rep ");
+ TEST_STRING(movs, "");
+ TEST_STRING(movs, "rep ");
+ TEST_STRING(lods, ""); /* to verify stos */
+
+ /* XXX: better tests */
+ TEST_STRING(scas, "");
+ TEST_STRING(scas, "repz ");
+ TEST_STRING(scas, "repnz ");
+ TEST_STRING(cmps, "");
+ TEST_STRING(cmps, "repz ");
+ TEST_STRING(cmps, "repnz ");
+}
+
+/* VM86 test */
+
+static inline void set_bit(uint8_t *a, unsigned int bit)
+{
+ a[bit / 8] |= (1 << (bit % 8));
+}
+
+static inline uint8_t *seg_to_linear(unsigned int seg, unsigned int reg)
+{
+ return (uint8_t *)((seg << 4) + (reg & 0xffff));
+}
+
+static inline void pushw(struct vm86_regs *r, int val)
+{
+ r->esp = (r->esp & ~0xffff) | ((r->esp - 2) & 0xffff);
+ *(uint16_t *)seg_to_linear(r->ss, r->esp) = val;
+}
+
+#undef __syscall_return
+#define __syscall_return(type, res) \
+do { \
+ return (type) (res); \
+} while (0)
+
+_syscall2(int, vm86, int, func, struct vm86plus_struct *, v86)
+
+extern char vm86_code_start;
+extern char vm86_code_end;
+
+#define VM86_CODE_CS 0x100
+#define VM86_CODE_IP 0x100
+
+void test_vm86(void)
+{
+ struct vm86plus_struct ctx;
+ struct vm86_regs *r;
+ uint8_t *vm86_mem;
+ int seg, ret;
+
+ vm86_mem = mmap((void *)0x00000000, 0x110000,
+ PROT_WRITE | PROT_READ | PROT_EXEC,
+ MAP_FIXED | MAP_ANON | MAP_PRIVATE, -1, 0);
+ if (vm86_mem == MAP_FAILED) {
+ printf("ERROR: could not map vm86 memory");
+ return;
+ }
+ memset(&ctx, 0, sizeof(ctx));
+
+ /* init basic registers */
+ r = &ctx.regs;
+ r->eip = VM86_CODE_IP;
+ r->esp = 0xfffe;
+ seg = VM86_CODE_CS;
+ r->cs = seg;
+ r->ss = seg;
+ r->ds = seg;
+ r->es = seg;
+ r->fs = seg;
+ r->gs = seg;
+ r->eflags = VIF_MASK;
+
+ /* move code to proper address. We use the same layout as a .com
+ dos program. */
+ memcpy(vm86_mem + (VM86_CODE_CS << 4) + VM86_CODE_IP,
+ &vm86_code_start, &vm86_code_end - &vm86_code_start);
+
+ /* mark int 0x21 as being emulated */
+ set_bit((uint8_t *)&ctx.int_revectored, 0x21);
+
+ for(;;) {
+ ret = vm86(VM86_ENTER, &ctx);
+ switch(VM86_TYPE(ret)) {
+ case VM86_INTx:
+ {
+ int int_num, ah, v;
+
+ int_num = VM86_ARG(ret);
+ if (int_num != 0x21)
+ goto unknown_int;
+ ah = (r->eax >> 8) & 0xff;
+ switch(ah) {
+ case 0x00: /* exit */
+ goto the_end;
+ case 0x02: /* write char */
+ {
+ uint8_t c = r->edx;
+ putchar(c);
+ }
+ break;
+ case 0x09: /* write string */
+ {
+ uint8_t c, *ptr;
+ ptr = seg_to_linear(r->ds, r->edx);
+ for(;;) {
+ c = *ptr++;
+ if (c == '$')
+ break;
+ putchar(c);
+ }
+ r->eax = (r->eax & ~0xff) | '$';
+ }
+ break;
+ case 0xff: /* extension: write eflags number in edx */
+ v = (int)r->edx;
+#ifndef LINUX_VM86_IOPL_FIX
+ v &= ~0x3000;
+#endif
+ printf("%08x\n", v);
+ break;
+ default:
+ unknown_int:
+ printf("unsupported int 0x%02x\n", int_num);
+ goto the_end;
+ }
+ }
+ break;
+ case VM86_SIGNAL:
+ /* a signal came, we just ignore that */
+ break;
+ case VM86_STI:
+ break;
+ default:
+ printf("ERROR: unhandled vm86 return code (0x%x)\n", ret);
+ goto the_end;
+ }
+ }
+ the_end:
+ printf("VM86 end\n");
+ munmap(vm86_mem, 0x110000);
+}
+
+/* exception tests */
+#ifndef REG_EAX
+#define REG_EAX EAX
+#define REG_EBX EBX
+#define REG_ECX ECX
+#define REG_EDX EDX
+#define REG_ESI ESI
+#define REG_EDI EDI
+#define REG_EBP EBP
+#define REG_ESP ESP
+#define REG_EIP EIP
+#define REG_EFL EFL
+#define REG_TRAPNO TRAPNO
+#define REG_ERR ERR
+#endif
+
+jmp_buf jmp_env;
+int v1;
+int tab[2];
+
+void sig_handler(int sig, siginfo_t *info, void *puc)
+{
+ struct ucontext *uc = puc;
+
+ printf("si_signo=%d si_errno=%d si_code=%d",
+ info->si_signo, info->si_errno, info->si_code);
+ printf(" si_addr=0x%08lx",
+ (unsigned long)info->si_addr);
+ printf("\n");
+
+ printf("trapno=0x%02x err=0x%08x",
+ uc->uc_mcontext.gregs[REG_TRAPNO],
+ uc->uc_mcontext.gregs[REG_ERR]);
+ printf(" EIP=0x%08x", uc->uc_mcontext.gregs[REG_EIP]);
+ printf("\n");
+ longjmp(jmp_env, 1);
+}
+
+void test_exceptions(void)
+{
+ struct modify_ldt_ldt_s ldt;
+ struct sigaction act;
+ volatile int val;
+
+ act.sa_sigaction = sig_handler;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_SIGINFO;
+ sigaction(SIGFPE, &act, NULL);
+ sigaction(SIGILL, &act, NULL);
+ sigaction(SIGSEGV, &act, NULL);
+ sigaction(SIGBUS, &act, NULL);
+ sigaction(SIGTRAP, &act, NULL);
+
+ /* test division by zero reporting */
+ printf("DIVZ exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ /* now divide by zero */
+ v1 = 0;
+ v1 = 2 / v1;
+ }
+
+ printf("BOUND exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ /* bound exception */
+ tab[0] = 1;
+ tab[1] = 10;
+ asm volatile ("bound %0, %1" : : "r" (11), "m" (tab[0]));
+ }
+
+ printf("segment exceptions:\n");
+ if (setjmp(jmp_env) == 0) {
+ /* load an invalid segment */
+ asm volatile ("movl %0, %%fs" : : "r" ((0x1234 << 3) | 1));
+ }
+ if (setjmp(jmp_env) == 0) {
+ /* null data segment is valid */
+ asm volatile ("movl %0, %%fs" : : "r" (3));
+ /* null stack segment */
+ asm volatile ("movl %0, %%ss" : : "r" (3));
+ }
+
+ ldt.entry_number = 1;
+ ldt.base_addr = (unsigned long)&seg_data1;
+ ldt.limit = (sizeof(seg_data1) + 0xfff) >> 12;
+ ldt.seg_32bit = 1;
+ ldt.contents = MODIFY_LDT_CONTENTS_DATA;
+ ldt.read_exec_only = 0;
+ ldt.limit_in_pages = 1;
+ ldt.seg_not_present = 1;
+ ldt.useable = 1;
+ modify_ldt(1, &ldt, sizeof(ldt)); /* write ldt entry */
+
+ if (setjmp(jmp_env) == 0) {
+ /* segment not present */
+ asm volatile ("movl %0, %%fs" : : "r" (MK_SEL(1)));
+ }
+
+ /* test SEGV reporting */
+ printf("PF exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ val = 1;
+ /* we add a nop to test a weird PC retrieval case */
+ asm volatile ("nop");
+ /* now store in an invalid address */
+ *(char *)0x1234 = 1;
+ }
+
+ /* test SEGV reporting */
+ printf("PF exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ val = 1;
+ /* read from an invalid address */
+ v1 = *(char *)0x1234;
+ }
+
+ /* test illegal instruction reporting */
+ printf("UD2 exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ /* now execute an invalid instruction */
+ asm volatile("ud2");
+ }
+ printf("lock nop exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ /* now execute an invalid instruction */
+ asm volatile("lock nop");
+ }
+
+ printf("INT exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ asm volatile ("int $0xfd");
+ }
+ if (setjmp(jmp_env) == 0) {
+ asm volatile ("int $0x01");
+ }
+ if (setjmp(jmp_env) == 0) {
+ asm volatile (".byte 0xcd, 0x03");
+ }
+ if (setjmp(jmp_env) == 0) {
+ asm volatile ("int $0x04");
+ }
+ if (setjmp(jmp_env) == 0) {
+ asm volatile ("int $0x05");
+ }
+
+ printf("INT3 exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ asm volatile ("int3");
+ }
+
+ printf("CLI exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ asm volatile ("cli");
+ }
+
+ printf("STI exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ asm volatile ("cli");
+ }
+
+ printf("INTO exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ /* overflow exception */
+ asm volatile ("addl $1, %0 ; into" : : "r" (0x7fffffff));
+ }
+
+ printf("OUTB exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ asm volatile ("outb %%al, %%dx" : : "d" (0x4321), "a" (0));
+ }
+
+ printf("INB exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ asm volatile ("inb %%dx, %%al" : "=a" (val) : "d" (0x4321));
+ }
+
+ printf("REP OUTSB exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ asm volatile ("rep outsb" : : "d" (0x4321), "S" (tab), "c" (1));
+ }
+
+ printf("REP INSB exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ asm volatile ("rep insb" : : "d" (0x4321), "D" (tab), "c" (1));
+ }
+
+ printf("HLT exception:\n");
+ if (setjmp(jmp_env) == 0) {
+ asm volatile ("hlt");
+ }
+
+ printf("single step exception:\n");
+ val = 0;
+ if (setjmp(jmp_env) == 0) {
+ asm volatile ("pushf\n"
+ "orl $0x00100, (%%esp)\n"
+ "popf\n"
+ "movl $0xabcd, %0\n"
+ "movl $0x0, %0\n" : "=m" (val) : : "cc", "memory");
+ }
+ printf("val=0x%x\n", val);
+}
+
+/* specific precise single step test */
+void sig_trap_handler(int sig, siginfo_t *info, void *puc)
+{
+ struct ucontext *uc = puc;
+ printf("EIP=0x%08x\n", uc->uc_mcontext.gregs[REG_EIP]);
+}
+
+const uint8_t sstep_buf1[4] = { 1, 2, 3, 4};
+uint8_t sstep_buf2[4];
+
+void test_single_step(void)
+{
+ struct sigaction act;
+ volatile int val;
+ int i;
+
+ val = 0;
+ act.sa_sigaction = sig_trap_handler;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = SA_SIGINFO;
+ sigaction(SIGTRAP, &act, NULL);
+ asm volatile ("pushf\n"
+ "orl $0x00100, (%%esp)\n"
+ "popf\n"
+ "movl $0xabcd, %0\n"
+
+ /* jmp test */
+ "movl $3, %%ecx\n"
+ "1:\n"
+ "addl $1, %0\n"
+ "decl %%ecx\n"
+ "jnz 1b\n"
+
+ /* movsb: the single step should stop at each movsb iteration */
+ "movl $sstep_buf1, %%esi\n"
+ "movl $sstep_buf2, %%edi\n"
+ "movl $0, %%ecx\n"
+ "rep movsb\n"
+ "movl $3, %%ecx\n"
+ "rep movsb\n"
+ "movl $1, %%ecx\n"
+ "rep movsb\n"
+
+ /* cmpsb: the single step should stop at each cmpsb iteration */
+ "movl $sstep_buf1, %%esi\n"
+ "movl $sstep_buf2, %%edi\n"
+ "movl $0, %%ecx\n"
+ "rep cmpsb\n"
+ "movl $4, %%ecx\n"
+ "rep cmpsb\n"
+
+ /* getpid() syscall: single step should skip one
+ instruction */
+ "movl $20, %%eax\n"
+ "int $0x80\n"
+ "movl $0, %%eax\n"
+
+ /* when modifying SS, trace is not done on the next
+ instruction */
+ "movl %%ss, %%ecx\n"
+ "movl %%ecx, %%ss\n"
+ "addl $1, %0\n"
+ "movl $1, %%eax\n"
+ "movl %%ecx, %%ss\n"
+ "jmp 1f\n"
+ "addl $1, %0\n"
+ "1:\n"
+ "movl $1, %%eax\n"
+ "pushl %%ecx\n"
+ "popl %%ss\n"
+ "addl $1, %0\n"
+ "movl $1, %%eax\n"
+
+ "pushf\n"
+ "andl $~0x00100, (%%esp)\n"
+ "popf\n"
+ : "=m" (val)
+ :
+ : "cc", "memory", "eax", "ecx", "esi", "edi");
+ printf("val=%d\n", val);
+ for(i = 0; i < 4; i++)
+ printf("sstep_buf2[%d] = %d\n", i, sstep_buf2[i]);
+}
+
+/* self modifying code test */
+uint8_t code[] = {
+ 0xb8, 0x1, 0x00, 0x00, 0x00, /* movl $1, %eax */
+ 0xc3, /* ret */
+};
+
+asm("smc_code2:\n"
+ "movl 4(%esp), %eax\n"
+ "movl %eax, smc_patch_addr2 + 1\n"
+ "nop\n"
+ "nop\n"
+ "nop\n"
+ "nop\n"
+ "nop\n"
+ "nop\n"
+ "nop\n"
+ "nop\n"
+ "smc_patch_addr2:\n"
+ "movl $1, %eax\n"
+ "ret\n");
+
+typedef int FuncType(void);
+extern int smc_code2(int);
+void test_self_modifying_code(void)
+{
+ int i;
+
+ printf("self modifying code:\n");
+ printf("func1 = 0x%x\n", ((FuncType *)code)());
+ for(i = 2; i <= 4; i++) {
+ code[1] = i;
+ printf("func%d = 0x%x\n", i, ((FuncType *)code)());
+ }
+
+ /* more difficult test : the modified code is just after the
+ modifying instruction. It is forbidden in Intel specs, but it
+ is used by old DOS programs */
+ for(i = 2; i <= 4; i++) {
+ printf("smc_code2(%d) = %d\n", i, smc_code2(i));
+ }
+}
+
+int enter_stack[4096];
+
+#define TEST_ENTER(size, stack_type, level)\
+{\
+ int esp_save, esp_val, ebp_val, ebp_save, i;\
+ stack_type *ptr, *stack_end, *stack_ptr;\
+ memset(enter_stack, 0, sizeof(enter_stack));\
+ stack_end = stack_ptr = (stack_type *)(enter_stack + 4096);\
+ ebp_val = (long)stack_ptr;\
+ for(i=1;i<=32;i++)\
+ *--stack_ptr = i;\
+ esp_val = (long)stack_ptr;\
+ asm("movl %%esp, %[esp_save]\n"\
+ "movl %%ebp, %[ebp_save]\n"\
+ "movl %[esp_val], %%esp\n"\
+ "movl %[ebp_val], %%ebp\n"\
+ "enter" size " $12, $" #level "\n"\
+ "movl %%esp, %[esp_val]\n"\
+ "movl %%ebp, %[ebp_val]\n"\
+ "movl %[esp_save], %%esp\n"\
+ "movl %[ebp_save], %%ebp\n"\
+ : [esp_save] "=r" (esp_save),\
+ [ebp_save] "=r" (ebp_save),\
+ [esp_val] "=r" (esp_val),\
+ [ebp_val] "=r" (ebp_val)\
+ : "[esp_val]" (esp_val),\
+ "[ebp_val]" (ebp_val));\
+ printf("level=%d:\n", level);\
+ printf("esp_val=0x%08lx\n", esp_val - (long)stack_end);\
+ printf("ebp_val=0x%08lx\n", ebp_val - (long)stack_end);\
+ for(ptr = (stack_type *)esp_val; ptr < stack_end; ptr++)\
+ printf("%08x\n", ptr[0]);\
+}
+
+static void test_enter(void)
+{
+ TEST_ENTER("l", uint32_t, 0);
+ TEST_ENTER("l", uint32_t, 1);
+ TEST_ENTER("l", uint32_t, 2);
+ TEST_ENTER("l", uint32_t, 31);
+
+ TEST_ENTER("w", uint16_t, 0);
+ TEST_ENTER("w", uint16_t, 1);
+ TEST_ENTER("w", uint16_t, 2);
+ TEST_ENTER("w", uint16_t, 31);
+}
+
+
+static void *call_end __init_call = NULL;
+
+int main(int argc, char **argv)
+{
+ void **ptr;
+ void (*func)(void);
+
+ ptr = &call_start + 1;
+ while (*ptr != NULL) {
+ func = *ptr++;
+ func();
+ }
+ test_bsx();
+ test_mul();
+ test_jcc();
+ test_floats();
+ test_bcd();
+ test_xchg();
+ test_string();
+ test_misc();
+ test_lea();
+ test_segs();
+ test_code16();
+ test_vm86();
+ test_exceptions();
+ test_self_modifying_code();
+ test_single_step();
+ test_enter();
+ return 0;
+}
--- /dev/null
+
+#define exec_op glue(exec_, OP)
+#define exec_opl glue(glue(exec_, OP), l)
+#define exec_opw glue(glue(exec_, OP), w)
+#define exec_opb glue(glue(exec_, OP), b)
+
+#define EXECOP2(size, res, s1, flags) \
+ asm ("push %4\n\t"\
+ "popf\n\t"\
+ stringify(OP) size " %" size "2, %" size "0\n\t" \
+ "pushf\n\t"\
+ "popl %1\n\t"\
+ : "=q" (res), "=g" (flags)\
+ : "q" (s1), "0" (res), "1" (flags));
+
+#define EXECOP1(size, res, flags) \
+ asm ("push %3\n\t"\
+ "popf\n\t"\
+ stringify(OP) size " %" size "0\n\t" \
+ "pushf\n\t"\
+ "popl %1\n\t"\
+ : "=q" (res), "=g" (flags)\
+ : "0" (res), "1" (flags));
+
+#ifdef OP1
+void exec_opl(int s0, int s1, int iflags)
+{
+ int res, flags;
+ res = s0;
+ flags = iflags;
+ EXECOP1("", res, flags);
+ printf("%-10s A=%08x R=%08x CCIN=%04x CC=%04x\n",
+ stringify(OP) "l", s0, res, iflags, flags & CC_MASK);
+}
+
+void exec_opw(int s0, int s1, int iflags)
+{
+ int res, flags;
+ res = s0;
+ flags = iflags;
+ EXECOP1("w", res, flags);
+ printf("%-10s A=%08x R=%08x CCIN=%04x CC=%04x\n",
+ stringify(OP) "w", s0, res, iflags, flags & CC_MASK);
+}
+
+void exec_opb(int s0, int s1, int iflags)
+{
+ int res, flags;
+ res = s0;
+ flags = iflags;
+ EXECOP1("b", res, flags);
+ printf("%-10s A=%08x R=%08x CCIN=%04x CC=%04x\n",
+ stringify(OP) "b", s0, res, iflags, flags & CC_MASK);
+}
+#else
+void exec_opl(int s0, int s1, int iflags)
+{
+ int res, flags;
+ res = s0;
+ flags = iflags;
+ EXECOP2("", res, s1, flags);
+ printf("%-10s A=%08x B=%08x R=%08x CCIN=%04x CC=%04x\n",
+ stringify(OP) "l", s0, s1, res, iflags, flags & CC_MASK);
+}
+
+void exec_opw(int s0, int s1, int iflags)
+{
+ int res, flags;
+ res = s0;
+ flags = iflags;
+ EXECOP2("w", res, s1, flags);
+ printf("%-10s A=%08x B=%08x R=%08x CCIN=%04x CC=%04x\n",
+ stringify(OP) "w", s0, s1, res, iflags, flags & CC_MASK);
+}
+
+void exec_opb(int s0, int s1, int iflags)
+{
+ int res, flags;
+ res = s0;
+ flags = iflags;
+ EXECOP2("b", res, s1, flags);
+ printf("%-10s A=%08x B=%08x R=%08x CCIN=%04x CC=%04x\n",
+ stringify(OP) "b", s0, s1, res, iflags, flags & CC_MASK);
+}
+#endif
+
+void exec_op(int s0, int s1)
+{
+ exec_opl(s0, s1, 0);
+ exec_opw(s0, s1, 0);
+ exec_opb(s0, s1, 0);
+#ifdef OP_CC
+ exec_opl(s0, s1, CC_C);
+ exec_opw(s0, s1, CC_C);
+ exec_opb(s0, s1, CC_C);
+#endif
+}
+
+void glue(test_, OP)(void)
+{
+ exec_op(0x12345678, 0x812FADA);
+ exec_op(0x12341, 0x12341);
+ exec_op(0x12341, -0x12341);
+ exec_op(0xffffffff, 0);
+ exec_op(0xffffffff, -1);
+ exec_op(0xffffffff, 1);
+ exec_op(0xffffffff, 2);
+ exec_op(0x7fffffff, 0);
+ exec_op(0x7fffffff, 1);
+ exec_op(0x7fffffff, -1);
+ exec_op(0x80000000, -1);
+ exec_op(0x80000000, 1);
+ exec_op(0x80000000, -2);
+ exec_op(0x12347fff, 0);
+ exec_op(0x12347fff, 1);
+ exec_op(0x12347fff, -1);
+ exec_op(0x12348000, -1);
+ exec_op(0x12348000, 1);
+ exec_op(0x12348000, -2);
+ exec_op(0x12347f7f, 0);
+ exec_op(0x12347f7f, 1);
+ exec_op(0x12347f7f, -1);
+ exec_op(0x12348080, -1);
+ exec_op(0x12348080, 1);
+ exec_op(0x12348080, -2);
+}
+
+void *glue(_test_, OP) __init_call = glue(test_, OP);
+
+#undef OP
+#undef OP_CC
--- /dev/null
+/* Test path override code */
+#define _GNU_SOURCE
+#include "../path.c"
+#include <stdarg.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+/* Any log message kills the test. */
+void gemu_log(const char *fmt, ...)
+{
+ va_list ap;
+
+ fprintf(stderr, "FATAL: ");
+ va_start(ap, fmt);
+ vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ exit(1);
+}
+
+#define NO_CHANGE(_path) \
+ do { \
+ if (strcmp(path(_path), _path) != 0) return __LINE__; \
+ } while(0)
+
+#define CHANGE_TO(_path, _newpath) \
+ do { \
+ if (strcmp(path(_path), _newpath) != 0) return __LINE__; \
+ } while(0)
+
+static void cleanup(void)
+{
+ unlink("/tmp/qemu-test_path/DIR1/DIR2/FILE");
+ unlink("/tmp/qemu-test_path/DIR1/DIR2/FILE2");
+ unlink("/tmp/qemu-test_path/DIR1/DIR2/FILE3");
+ unlink("/tmp/qemu-test_path/DIR1/DIR2/FILE4");
+ unlink("/tmp/qemu-test_path/DIR1/DIR2/FILE5");
+ rmdir("/tmp/qemu-test_path/DIR1/DIR2");
+ rmdir("/tmp/qemu-test_path/DIR1/DIR3");
+ rmdir("/tmp/qemu-test_path/DIR1");
+ rmdir("/tmp/qemu-test_path");
+}
+
+static unsigned int do_test(void)
+{
+ if (mkdir("/tmp/qemu-test_path", 0700) != 0)
+ return __LINE__;
+
+ if (mkdir("/tmp/qemu-test_path/DIR1", 0700) != 0)
+ return __LINE__;
+
+ if (mkdir("/tmp/qemu-test_path/DIR1/DIR2", 0700) != 0)
+ return __LINE__;
+
+ if (mkdir("/tmp/qemu-test_path/DIR1/DIR3", 0700) != 0)
+ return __LINE__;
+
+ if (close(creat("/tmp/qemu-test_path/DIR1/DIR2/FILE", 0600)) != 0)
+ return __LINE__;
+
+ if (close(creat("/tmp/qemu-test_path/DIR1/DIR2/FILE2", 0600)) != 0)
+ return __LINE__;
+
+ if (close(creat("/tmp/qemu-test_path/DIR1/DIR2/FILE3", 0600)) != 0)
+ return __LINE__;
+
+ if (close(creat("/tmp/qemu-test_path/DIR1/DIR2/FILE4", 0600)) != 0)
+ return __LINE__;
+
+ if (close(creat("/tmp/qemu-test_path/DIR1/DIR2/FILE5", 0600)) != 0)
+ return __LINE__;
+
+ init_paths("/tmp/qemu-test_path");
+
+ NO_CHANGE("/tmp");
+ NO_CHANGE("/tmp/");
+ NO_CHANGE("/tmp/qemu-test_path");
+ NO_CHANGE("/tmp/qemu-test_path/");
+ NO_CHANGE("/tmp/qemu-test_path/D");
+ NO_CHANGE("/tmp/qemu-test_path/DI");
+ NO_CHANGE("/tmp/qemu-test_path/DIR");
+ NO_CHANGE("/tmp/qemu-test_path/DIR1");
+ NO_CHANGE("/tmp/qemu-test_path/DIR1/");
+
+ NO_CHANGE("/D");
+ NO_CHANGE("/DI");
+ NO_CHANGE("/DIR");
+ NO_CHANGE("/DIR2");
+ NO_CHANGE("/DIR1.");
+
+ CHANGE_TO("/DIR1", "/tmp/qemu-test_path/DIR1");
+ CHANGE_TO("/DIR1/", "/tmp/qemu-test_path/DIR1");
+
+ NO_CHANGE("/DIR1/D");
+ NO_CHANGE("/DIR1/DI");
+ NO_CHANGE("/DIR1/DIR");
+ NO_CHANGE("/DIR1/DIR1");
+
+ CHANGE_TO("/DIR1/DIR2", "/tmp/qemu-test_path/DIR1/DIR2");
+ CHANGE_TO("/DIR1/DIR2/", "/tmp/qemu-test_path/DIR1/DIR2");
+
+ CHANGE_TO("/DIR1/DIR3", "/tmp/qemu-test_path/DIR1/DIR3");
+ CHANGE_TO("/DIR1/DIR3/", "/tmp/qemu-test_path/DIR1/DIR3");
+
+ NO_CHANGE("/DIR1/DIR2/F");
+ NO_CHANGE("/DIR1/DIR2/FI");
+ NO_CHANGE("/DIR1/DIR2/FIL");
+ NO_CHANGE("/DIR1/DIR2/FIL.");
+
+ CHANGE_TO("/DIR1/DIR2/FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
+ CHANGE_TO("/DIR1/DIR2/FILE2", "/tmp/qemu-test_path/DIR1/DIR2/FILE2");
+ CHANGE_TO("/DIR1/DIR2/FILE3", "/tmp/qemu-test_path/DIR1/DIR2/FILE3");
+ CHANGE_TO("/DIR1/DIR2/FILE4", "/tmp/qemu-test_path/DIR1/DIR2/FILE4");
+ CHANGE_TO("/DIR1/DIR2/FILE5", "/tmp/qemu-test_path/DIR1/DIR2/FILE5");
+
+ NO_CHANGE("/DIR1/DIR2/FILE6");
+ NO_CHANGE("/DIR1/DIR2/FILE/X");
+
+ CHANGE_TO("/DIR1/../DIR1", "/tmp/qemu-test_path/DIR1");
+ CHANGE_TO("/DIR1/../DIR1/", "/tmp/qemu-test_path/DIR1");
+ CHANGE_TO("/../DIR1", "/tmp/qemu-test_path/DIR1");
+ CHANGE_TO("/../DIR1/", "/tmp/qemu-test_path/DIR1");
+ CHANGE_TO("/DIR1/DIR2/../DIR2", "/tmp/qemu-test_path/DIR1/DIR2");
+ CHANGE_TO("/DIR1/DIR2/../DIR2/../../DIR1/DIR2/FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
+ CHANGE_TO("/DIR1/DIR2/../DIR2/FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
+
+ NO_CHANGE("/DIR1/DIR2/../DIR1");
+ NO_CHANGE("/DIR1/DIR2/../FILE");
+
+ CHANGE_TO("/./DIR1/DIR2/FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
+ CHANGE_TO("/././DIR1/DIR2/FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
+ CHANGE_TO("/DIR1/./DIR2/FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
+ CHANGE_TO("/DIR1/././DIR2/FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
+ CHANGE_TO("/DIR1/DIR2/./FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
+ CHANGE_TO("/DIR1/DIR2/././FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
+ CHANGE_TO("/./DIR1/./DIR2/./FILE", "/tmp/qemu-test_path/DIR1/DIR2/FILE");
+
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ int ret;
+
+ ret = do_test();
+ cleanup();
+ if (ret) {
+ fprintf(stderr, "test_path: failed on line %i\n", ret);
+ return 1;
+ }
+ return 0;
+}
+
--- /dev/null
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <inttypes.h>
+#include <pthread.h>
+#include <sys/wait.h>
+#include <sched.h>
+
+void *thread1_func(void *arg)
+{
+ int i;
+ char buf[512];
+
+ for(i=0;i<10;i++) {
+ snprintf(buf, sizeof(buf), "thread1: %d %s\n", i, (char *)arg);
+ write(1, buf, strlen(buf));
+ usleep(100 * 1000);
+ }
+ return NULL;
+}
+
+void *thread2_func(void *arg)
+{
+ int i;
+ char buf[512];
+ for(i=0;i<20;i++) {
+ snprintf(buf, sizeof(buf), "thread2: %d %s\n", i, (char *)arg);
+ write(1, buf, strlen(buf));
+ usleep(150 * 1000);
+ }
+ return NULL;
+}
+
+void test_pthread(void)
+{
+ pthread_t tid1, tid2;
+
+ pthread_create(&tid1, NULL, thread1_func, "hello1");
+ pthread_create(&tid2, NULL, thread2_func, "hello2");
+ pthread_join(tid1, NULL);
+ pthread_join(tid2, NULL);
+ printf("End of pthread test.\n");
+}
+
+int main(int argc, char **argv)
+{
+ test_pthread();
+ return 0;
+}
--- /dev/null
+#! /usr/bin/perl -w
+
+# Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc.
+
+# This file is part of GNU CC.
+
+# GNU CC is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+
+# GNU CC is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with GNU CC; see the file COPYING. If not, write to
+# the Free Software Foundation, 59 Temple Place - Suite 330,
+# Boston MA 02111-1307, USA.
+
+# This does trivial (and I mean _trivial_) conversion of Texinfo
+# markup to Perl POD format. It's intended to be used to extract
+# something suitable for a manpage from a Texinfo document.
+
+$output = 0;
+$skipping = 0;
+%sects = ();
+$section = "";
+@icstack = ();
+@endwstack = ();
+@skstack = ();
+@instack = ();
+$shift = "";
+%defs = ();
+$fnno = 1;
+$inf = "";
+$ibase = "";
+
+while ($_ = shift) {
+ if (/^-D(.*)$/) {
+ if ($1 ne "") {
+ $flag = $1;
+ } else {
+ $flag = shift;
+ }
+ $value = "";
+ ($flag, $value) = ($flag =~ /^([^=]+)(?:=(.+))?/);
+ die "no flag specified for -D\n"
+ unless $flag ne "";
+ die "flags may only contain letters, digits, hyphens, dashes and underscores\n"
+ unless $flag =~ /^[a-zA-Z0-9_-]+$/;
+ $defs{$flag} = $value;
+ } elsif (/^-/) {
+ usage();
+ } else {
+ $in = $_, next unless defined $in;
+ $out = $_, next unless defined $out;
+ usage();
+ }
+}
+
+if (defined $in) {
+ $inf = gensym();
+ open($inf, "<$in") or die "opening \"$in\": $!\n";
+ $ibase = $1 if $in =~ m|^(.+)/[^/]+$|;
+} else {
+ $inf = \*STDIN;
+}
+
+if (defined $out) {
+ open(STDOUT, ">$out") or die "opening \"$out\": $!\n";
+}
+
+while(defined $inf) {
+while(<$inf>) {
+ # Certain commands are discarded without further processing.
+ /^\@(?:
+ [a-z]+index # @*index: useful only in complete manual
+ |need # @need: useful only in printed manual
+ |(?:end\s+)?group # @group .. @end group: ditto
+ |page # @page: ditto
+ |node # @node: useful only in .info file
+ |(?:end\s+)?ifnottex # @ifnottex .. @end ifnottex: use contents
+ )\b/x and next;
+
+ chomp;
+
+ # Look for filename and title markers.
+ /^\@setfilename\s+([^.]+)/ and $fn = $1, next;
+ /^\@settitle\s+([^.]+)/ and $tl = postprocess($1), next;
+
+ # Identify a man title but keep only the one we are interested in.
+ /^\@c\s+man\s+title\s+([A-Za-z0-9-]+)\s+(.+)/ and do {
+ if (exists $defs{$1}) {
+ $fn = $1;
+ $tl = postprocess($2);
+ }
+ next;
+ };
+
+ # Look for blocks surrounded by @c man begin SECTION ... @c man end.
+ # This really oughta be @ifman ... @end ifman and the like, but such
+ # would require rev'ing all other Texinfo translators.
+ /^\@c\s+man\s+begin\s+([A-Z]+)\s+([A-Za-z0-9-]+)/ and do {
+ $output = 1 if exists $defs{$2};
+ $sect = $1;
+ next;
+ };
+ /^\@c\s+man\s+begin\s+([A-Z]+)/ and $sect = $1, $output = 1, next;
+ /^\@c\s+man\s+end/ and do {
+ $sects{$sect} = "" unless exists $sects{$sect};
+ $sects{$sect} .= postprocess($section);
+ $section = "";
+ $output = 0;
+ next;
+ };
+
+ # handle variables
+ /^\@set\s+([a-zA-Z0-9_-]+)\s*(.*)$/ and do {
+ $defs{$1} = $2;
+ next;
+ };
+ /^\@clear\s+([a-zA-Z0-9_-]+)/ and do {
+ delete $defs{$1};
+ next;
+ };
+
+ next unless $output;
+
+ # Discard comments. (Can't do it above, because then we'd never see
+ # @c man lines.)
+ /^\@c\b/ and next;
+
+ # End-block handler goes up here because it needs to operate even
+ # if we are skipping.
+ /^\@end\s+([a-z]+)/ and do {
+ # Ignore @end foo, where foo is not an operation which may
+ # cause us to skip, if we are presently skipping.
+ my $ended = $1;
+ next if $skipping && $ended !~ /^(?:ifset|ifclear|ignore|menu|iftex)$/;
+
+ die "\@end $ended without \@$ended at line $.\n" unless defined $endw;
+ die "\@$endw ended by \@end $ended at line $.\n" unless $ended eq $endw;
+
+ $endw = pop @endwstack;
+
+ if ($ended =~ /^(?:ifset|ifclear|ignore|menu|iftex)$/) {
+ $skipping = pop @skstack;
+ next;
+ } elsif ($ended =~ /^(?:example|smallexample|display)$/) {
+ $shift = "";
+ $_ = ""; # need a paragraph break
+ } elsif ($ended =~ /^(?:itemize|enumerate|[fv]?table)$/) {
+ $_ = "\n=back\n";
+ $ic = pop @icstack;
+ } else {
+ die "unknown command \@end $ended at line $.\n";
+ }
+ };
+
+ # We must handle commands which can cause skipping even while we
+ # are skipping, otherwise we will not process nested conditionals
+ # correctly.
+ /^\@ifset\s+([a-zA-Z0-9_-]+)/ and do {
+ push @endwstack, $endw;
+ push @skstack, $skipping;
+ $endw = "ifset";
+ $skipping = 1 unless exists $defs{$1};
+ next;
+ };
+
+ /^\@ifclear\s+([a-zA-Z0-9_-]+)/ and do {
+ push @endwstack, $endw;
+ push @skstack, $skipping;
+ $endw = "ifclear";
+ $skipping = 1 if exists $defs{$1};
+ next;
+ };
+
+ /^\@(ignore|menu|iftex)\b/ and do {
+ push @endwstack, $endw;
+ push @skstack, $skipping;
+ $endw = $1;
+ $skipping = 1;
+ next;
+ };
+
+ next if $skipping;
+
+ # Character entities. First the ones that can be replaced by raw text
+ # or discarded outright:
+ s/\@copyright\{\}/(c)/g;
+ s/\@dots\{\}/.../g;
+ s/\@enddots\{\}/..../g;
+ s/\@([.!? ])/$1/g;
+ s/\@[:-]//g;
+ s/\@bullet(?:\{\})?/*/g;
+ s/\@TeX\{\}/TeX/g;
+ s/\@pounds\{\}/\#/g;
+ s/\@minus(?:\{\})?/-/g;
+ s/\\,/,/g;
+
+ # Now the ones that have to be replaced by special escapes
+ # (which will be turned back into text by unmunge())
+ s/&/&/g;
+ s/\@\{/{/g;
+ s/\@\}/}/g;
+ s/\@\@/&at;/g;
+
+ # Inside a verbatim block, handle @var specially.
+ if ($shift ne "") {
+ s/\@var\{([^\}]*)\}/<$1>/g;
+ }
+
+ # POD doesn't interpret E<> inside a verbatim block.
+ if ($shift eq "") {
+ s/</</g;
+ s/>/>/g;
+ } else {
+ s/</</g;
+ s/>/>/g;
+ }
+
+ # Single line command handlers.
+
+ /^\@include\s+(.+)$/ and do {
+ push @instack, $inf;
+ $inf = gensym();
+
+ # Try cwd and $ibase.
+ open($inf, "<" . $1)
+ or open($inf, "<" . $ibase . "/" . $1)
+ or die "cannot open $1 or $ibase/$1: $!\n";
+ next;
+ };
+
+ /^\@(?:section|unnumbered|unnumberedsec|center)\s+(.+)$/
+ and $_ = "\n=head2 $1\n";
+ /^\@subsection\s+(.+)$/
+ and $_ = "\n=head3 $1\n";
+
+ # Block command handlers:
+ /^\@itemize\s+(\@[a-z]+|\*|-)/ and do {
+ push @endwstack, $endw;
+ push @icstack, $ic;
+ $ic = $1;
+ $_ = "\n=over 4\n";
+ $endw = "itemize";
+ };
+
+ /^\@enumerate(?:\s+([a-zA-Z0-9]+))?/ and do {
+ push @endwstack, $endw;
+ push @icstack, $ic;
+ if (defined $1) {
+ $ic = $1 . ".";
+ } else {
+ $ic = "1.";
+ }
+ $_ = "\n=over 4\n";
+ $endw = "enumerate";
+ };
+
+ /^\@([fv]?table)\s+(\@[a-z]+)/ and do {
+ push @endwstack, $endw;
+ push @icstack, $ic;
+ $endw = $1;
+ $ic = $2;
+ $ic =~ s/\@(?:samp|strong|key|gcctabopt|option|env)/B/;
+ $ic =~ s/\@(?:code|kbd)/C/;
+ $ic =~ s/\@(?:dfn|var|emph|cite|i)/I/;
+ $ic =~ s/\@(?:file)/F/;
+ $_ = "\n=over 4\n";
+ };
+
+ /^\@((?:small)?example|display)/ and do {
+ push @endwstack, $endw;
+ $endw = $1;
+ $shift = "\t";
+ $_ = ""; # need a paragraph break
+ };
+
+ /^\@itemx?\s*(.+)?$/ and do {
+ if (defined $1) {
+ # Entity escapes prevent munging by the <> processing below.
+# print "$ic\n";
+ $_ = "\n=item $ic\<$1\>\n";
+ } else {
+ $_ = "\n=item $ic\n";
+ $ic =~ y/A-Ya-y/B-Zb-z/;
+ $ic =~ s/(\d+)/$1 + 1/eg;
+ }
+ };
+
+ $section .= $shift.$_."\n";
+}
+# End of current file.
+close($inf);
+$inf = pop @instack;
+}
+
+die "No filename or title\n" unless defined $fn && defined $tl;
+
+$sects{NAME} = "$fn \- $tl\n";
+$sects{FOOTNOTES} .= "=back\n" if exists $sects{FOOTNOTES};
+
+for $sect (qw(NAME SYNOPSIS DESCRIPTION OPTIONS ENVIRONMENT FILES
+ BUGS NOTES FOOTNOTES SEEALSO AUTHOR COPYRIGHT)) {
+ if(exists $sects{$sect}) {
+ $head = $sect;
+ $head =~ s/SEEALSO/SEE ALSO/;
+ print "=head1 $head\n\n";
+ print scalar unmunge ($sects{$sect});
+ print "\n";
+ }
+}
+
+sub usage
+{
+ die "usage: $0 [-D toggle...] [infile [outfile]]\n";
+}
+
+sub postprocess
+{
+ local $_ = $_[0];
+
+ # @value{foo} is replaced by whatever 'foo' is defined as.
+ while (m/(\@value\{([a-zA-Z0-9_-]+)\})/g) {
+ if (! exists $defs{$2}) {
+ print STDERR "Option $2 not defined\n";
+ s/\Q$1\E//;
+ } else {
+ $value = $defs{$2};
+ s/\Q$1\E/$value/;
+ }
+ }
+
+ # Formatting commands.
+ # Temporary escape for @r.
+ s/\@r\{([^\}]*)\}/R<$1>/g;
+ s/\@(?:dfn|var|emph|cite|i)\{([^\}]*)\}/I<$1>/g;
+ s/\@(?:code|kbd)\{([^\}]*)\}/C<$1>/g;
+ s/\@(?:gccoptlist|samp|strong|key|option|env|command|b)\{([^\}]*)\}/B<$1>/g;
+ s/\@sc\{([^\}]*)\}/\U$1/g;
+ s/\@file\{([^\}]*)\}/F<$1>/g;
+ s/\@w\{([^\}]*)\}/S<$1>/g;
+ s/\@(?:dmn|math)\{([^\}]*)\}/$1/g;
+
+ # Cross references are thrown away, as are @noindent and @refill.
+ # (@noindent is impossible in .pod, and @refill is unnecessary.)
+ # @* is also impossible in .pod; we discard it and any newline that
+ # follows it. Similarly, our macro @gol must be discarded.
+
+ s/\(?\@xref\{(?:[^\}]*)\}(?:[^.<]|(?:<[^<>]*>))*\.\)?//g;
+ s/\s+\(\@pxref\{(?:[^\}]*)\}\)//g;
+ s/;\s+\@pxref\{(?:[^\}]*)\}//g;
+ s/\@noindent\s*//g;
+ s/\@refill//g;
+ s/\@gol//g;
+ s/\@\*\s*\n?//g;
+
+ # @uref can take one, two, or three arguments, with different
+ # semantics each time. @url and @email are just like @uref with
+ # one argument, for our purposes.
+ s/\@(?:uref|url|email)\{([^\},]*)\}/<B<$1>>/g;
+ s/\@uref\{([^\},]*),([^\},]*)\}/$2 (C<$1>)/g;
+ s/\@uref\{([^\},]*),([^\},]*),([^\},]*)\}/$3/g;
+
+ # Turn B<blah I<blah> blah> into B<blah> I<blah> B<blah> to
+ # match Texinfo semantics of @emph inside @samp. Also handle @r
+ # inside bold.
+ s/</</g;
+ s/>/>/g;
+ 1 while s/B<((?:[^<>]|I<[^<>]*>)*)R<([^>]*)>/B<$1>${2}B</g;
+ 1 while (s/B<([^<>]*)I<([^>]+)>/B<$1>I<$2>B</g);
+ 1 while (s/I<([^<>]*)B<([^>]+)>/I<$1>B<$2>I</g);
+ s/[BI]<>//g;
+ s/([BI])<(\s+)([^>]+)>/$2$1<$3>/g;
+ s/([BI])<([^>]+?)(\s+)>/$1<$2>$3/g;
+
+ # Extract footnotes. This has to be done after all other
+ # processing because otherwise the regexp will choke on formatting
+ # inside @footnote.
+ while (/\@footnote/g) {
+ s/\@footnote\{([^\}]+)\}/[$fnno]/;
+ add_footnote($1, $fnno);
+ $fnno++;
+ }
+
+ return $_;
+}
+
+sub unmunge
+{
+ # Replace escaped symbols with their equivalents.
+ local $_ = $_[0];
+
+ s/</E<lt>/g;
+ s/>/E<gt>/g;
+ s/{/\{/g;
+ s/}/\}/g;
+ s/&at;/\@/g;
+ s/&/&/g;
+ return $_;
+}
+
+sub add_footnote
+{
+ unless (exists $sects{FOOTNOTES}) {
+ $sects{FOOTNOTES} = "\n=over 4\n\n";
+ }
+
+ $sects{FOOTNOTES} .= "=item $fnno.\n\n"; $fnno++;
+ $sects{FOOTNOTES} .= $_[0];
+ $sects{FOOTNOTES} .= "\n\n";
+}
+
+# stolen from Symbol.pm
+{
+ my $genseq = 0;
+ sub gensym
+ {
+ my $name = "GEN" . $genseq++;
+ my $ref = \*{$name};
+ delete $::{$name};
+ return $ref;
+ }
+}
--- /dev/null
+/*
+ * Generic thunking code to convert data between host and target CPU
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "qemu.h"
+#include "thunk.h"
+
+//#define DEBUG
+
+#define MAX_STRUCTS 128
+
+/* XXX: make it dynamic */
+StructEntry struct_entries[MAX_STRUCTS];
+
+static inline const argtype *thunk_type_next(const argtype *type_ptr)
+{
+ int type;
+
+ type = *type_ptr++;
+ switch(type) {
+ case TYPE_CHAR:
+ case TYPE_SHORT:
+ case TYPE_INT:
+ case TYPE_LONGLONG:
+ case TYPE_ULONGLONG:
+ case TYPE_LONG:
+ case TYPE_ULONG:
+ case TYPE_PTRVOID:
+ return type_ptr;
+ case TYPE_PTR:
+ return thunk_type_next(type_ptr);
+ case TYPE_ARRAY:
+ return thunk_type_next(type_ptr + 1);
+ case TYPE_STRUCT:
+ return type_ptr + 1;
+ default:
+ return NULL;
+ }
+}
+
+void thunk_register_struct(int id, const char *name, const argtype *types)
+{
+ const argtype *type_ptr;
+ StructEntry *se;
+ int nb_fields, offset, max_align, align, size, i, j;
+
+ se = struct_entries + id;
+
+ /* first we count the number of fields */
+ type_ptr = types;
+ nb_fields = 0;
+ while (*type_ptr != TYPE_NULL) {
+ type_ptr = thunk_type_next(type_ptr);
+ nb_fields++;
+ }
+ se->field_types = types;
+ se->nb_fields = nb_fields;
+ se->name = name;
+#ifdef DEBUG
+ printf("struct %s: id=%d nb_fields=%d\n",
+ se->name, id, se->nb_fields);
+#endif
+ /* now we can alloc the data */
+
+ for(i = 0;i < 2; i++) {
+ offset = 0;
+ max_align = 1;
+ se->field_offsets[i] = malloc(nb_fields * sizeof(int));
+ type_ptr = se->field_types;
+ for(j = 0;j < nb_fields; j++) {
+ size = thunk_type_size(type_ptr, i);
+ align = thunk_type_align(type_ptr, i);
+ offset = (offset + align - 1) & ~(align - 1);
+ se->field_offsets[i][j] = offset;
+ offset += size;
+ if (align > max_align)
+ max_align = align;
+ type_ptr = thunk_type_next(type_ptr);
+ }
+ offset = (offset + max_align - 1) & ~(max_align - 1);
+ se->size[i] = offset;
+ se->align[i] = max_align;
+#ifdef DEBUG
+ printf("%s: size=%d align=%d\n",
+ i == THUNK_HOST ? "host" : "target", offset, max_align);
+#endif
+ }
+}
+
+void thunk_register_struct_direct(int id, const char *name, StructEntry *se1)
+{
+ StructEntry *se;
+ se = struct_entries + id;
+ *se = *se1;
+ se->name = name;
+}
+
+
+/* now we can define the main conversion functions */
+const argtype *thunk_convert(void *dst, const void *src,
+ const argtype *type_ptr, int to_host)
+{
+ int type;
+
+ type = *type_ptr++;
+ switch(type) {
+ case TYPE_CHAR:
+ *(uint8_t *)dst = *(uint8_t *)src;
+ break;
+ case TYPE_SHORT:
+ *(uint16_t *)dst = tswap16(*(uint16_t *)src);
+ break;
+ case TYPE_INT:
+ *(uint32_t *)dst = tswap32(*(uint32_t *)src);
+ break;
+ case TYPE_LONGLONG:
+ case TYPE_ULONGLONG:
+ *(uint64_t *)dst = tswap64(*(uint64_t *)src);
+ break;
+#if HOST_LONG_BITS == 32 && TARGET_LONG_BITS == 32
+ case TYPE_LONG:
+ case TYPE_ULONG:
+ case TYPE_PTRVOID:
+ *(uint32_t *)dst = tswap32(*(uint32_t *)src);
+ break;
+#elif HOST_LONG_BITS == 64 && TARGET_LONG_BITS == 32
+ case TYPE_LONG:
+ case TYPE_ULONG:
+ case TYPE_PTRVOID:
+ if (to_host) {
+ *(uint64_t *)dst = tswap32(*(uint32_t *)src);
+ } else {
+ *(uint32_t *)dst = tswap32(*(uint64_t *)src & 0xffffffff);
+ }
+ break;
+#else
+#error unsupported conversion
+#endif
+ case TYPE_ARRAY:
+ {
+ int array_length, i, dst_size, src_size;
+ const uint8_t *s;
+ uint8_t *d;
+
+ array_length = *type_ptr++;
+ dst_size = thunk_type_size(type_ptr, to_host);
+ src_size = thunk_type_size(type_ptr, 1 - to_host);
+ d = dst;
+ s = src;
+ for(i = 0;i < array_length; i++) {
+ thunk_convert(d, s, type_ptr, to_host);
+ d += dst_size;
+ s += src_size;
+ }
+ type_ptr = thunk_type_next(type_ptr);
+ }
+ break;
+ case TYPE_STRUCT:
+ {
+ int i;
+ const StructEntry *se;
+ const uint8_t *s;
+ uint8_t *d;
+ const argtype *field_types;
+ const int *dst_offsets, *src_offsets;
+
+ se = struct_entries + *type_ptr++;
+ if (se->convert[0] != NULL) {
+ /* specific conversion is needed */
+ (*se->convert[to_host])(dst, src);
+ } else {
+ /* standard struct conversion */
+ field_types = se->field_types;
+ dst_offsets = se->field_offsets[to_host];
+ src_offsets = se->field_offsets[1 - to_host];
+ d = dst;
+ s = src;
+ for(i = 0;i < se->nb_fields; i++) {
+ field_types = thunk_convert(d + dst_offsets[i],
+ s + src_offsets[i],
+ field_types, to_host);
+ }
+ }
+ }
+ break;
+ default:
+ fprintf(stderr, "Invalid type 0x%x\n", type);
+ break;
+ }
+ return type_ptr;
+}
+
+/* from em86 */
+
+/* Utility function: Table-driven functions to translate bitmasks
+ * between X86 and Alpha formats...
+ */
+unsigned int target_to_host_bitmask(unsigned int x86_mask,
+ bitmask_transtbl * trans_tbl)
+{
+ bitmask_transtbl * btp;
+ unsigned int alpha_mask = 0;
+
+ for(btp = trans_tbl; btp->x86_mask && btp->alpha_mask; btp++) {
+ if((x86_mask & btp->x86_mask) == btp->x86_bits) {
+ alpha_mask |= btp->alpha_bits;
+ }
+ }
+ return(alpha_mask);
+}
+
+unsigned int host_to_target_bitmask(unsigned int alpha_mask,
+ bitmask_transtbl * trans_tbl)
+{
+ bitmask_transtbl * btp;
+ unsigned int x86_mask = 0;
+
+ for(btp = trans_tbl; btp->x86_mask && btp->alpha_mask; btp++) {
+ if((alpha_mask & btp->alpha_mask) == btp->alpha_bits) {
+ x86_mask |= btp->x86_bits;
+ }
+ }
+ return(x86_mask);
+}
--- /dev/null
+/*
+ * Generic thunking code to convert data between host and target CPU
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#ifndef THUNK_H
+#define THUNK_H
+
+#include <inttypes.h>
+#include "cpu.h"
+
+/* types enums definitions */
+
+typedef enum argtype {
+ TYPE_NULL,
+ TYPE_CHAR,
+ TYPE_SHORT,
+ TYPE_INT,
+ TYPE_LONG,
+ TYPE_ULONG,
+ TYPE_PTRVOID, /* pointer on unknown data */
+ TYPE_LONGLONG,
+ TYPE_ULONGLONG,
+ TYPE_PTR,
+ TYPE_ARRAY,
+ TYPE_STRUCT,
+} argtype;
+
+#define MK_PTR(type) TYPE_PTR, type
+#define MK_ARRAY(type, size) TYPE_ARRAY, size, type
+#define MK_STRUCT(id) TYPE_STRUCT, id
+
+#define THUNK_TARGET 0
+#define THUNK_HOST 1
+
+typedef struct {
+ /* standard struct handling */
+ const argtype *field_types;
+ int nb_fields;
+ int *field_offsets[2];
+ /* special handling */
+ void (*convert[2])(void *dst, const void *src);
+ int size[2];
+ int align[2];
+ const char *name;
+} StructEntry;
+
+/* Translation table for bitmasks... */
+typedef struct bitmask_transtbl {
+ unsigned int x86_mask;
+ unsigned int x86_bits;
+ unsigned int alpha_mask;
+ unsigned int alpha_bits;
+} bitmask_transtbl;
+
+void thunk_register_struct(int id, const char *name, const argtype *types);
+void thunk_register_struct_direct(int id, const char *name, StructEntry *se1);
+const argtype *thunk_convert(void *dst, const void *src,
+ const argtype *type_ptr, int to_host);
+#ifndef NO_THUNK_TYPE_SIZE
+
+extern StructEntry struct_entries[];
+
+static inline int thunk_type_size(const argtype *type_ptr, int is_host)
+{
+ int type, size;
+ const StructEntry *se;
+
+ type = *type_ptr;
+ switch(type) {
+ case TYPE_CHAR:
+ return 1;
+ case TYPE_SHORT:
+ return 2;
+ case TYPE_INT:
+ return 4;
+ case TYPE_LONGLONG:
+ case TYPE_ULONGLONG:
+ return 8;
+ case TYPE_LONG:
+ case TYPE_ULONG:
+ case TYPE_PTRVOID:
+ case TYPE_PTR:
+ if (is_host) {
+ return HOST_LONG_SIZE;
+ } else {
+ return TARGET_LONG_SIZE;
+ }
+ break;
+ case TYPE_ARRAY:
+ size = type_ptr[1];
+ return size * thunk_type_size(type_ptr + 2, is_host);
+ case TYPE_STRUCT:
+ se = struct_entries + type_ptr[1];
+ return se->size[is_host];
+ default:
+ return -1;
+ }
+}
+
+static inline int thunk_type_align(const argtype *type_ptr, int is_host)
+{
+ int type;
+ const StructEntry *se;
+
+ type = *type_ptr;
+ switch(type) {
+ case TYPE_CHAR:
+ return 1;
+ case TYPE_SHORT:
+ return 2;
+ case TYPE_INT:
+ return 4;
+ case TYPE_LONGLONG:
+ case TYPE_ULONGLONG:
+ return 8;
+ case TYPE_LONG:
+ case TYPE_ULONG:
+ case TYPE_PTRVOID:
+ case TYPE_PTR:
+ if (is_host) {
+ return HOST_LONG_SIZE;
+ } else {
+ return TARGET_LONG_SIZE;
+ }
+ break;
+ case TYPE_ARRAY:
+ return thunk_type_align(type_ptr + 2, is_host);
+ case TYPE_STRUCT:
+ se = struct_entries + type_ptr[1];
+ return se->align[is_host];
+ default:
+ return -1;
+ }
+}
+
+#endif /* NO_THUNK_TYPE_SIZE */
+
+unsigned int target_to_host_bitmask(unsigned int x86_mask,
+ bitmask_transtbl * trans_tbl);
+unsigned int host_to_target_bitmask(unsigned int alpha_mask,
+ bitmask_transtbl * trans_tbl);
+
+#endif
--- /dev/null
+static uint8_t vgafont16[256 * 16] = {
+
+ /* 0 0x00 '^@' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 1 0x01 '^A' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0x81, /* 10000001 */
+ 0xa5, /* 10100101 */
+ 0x81, /* 10000001 */
+ 0x81, /* 10000001 */
+ 0xbd, /* 10111101 */
+ 0x99, /* 10011001 */
+ 0x81, /* 10000001 */
+ 0x81, /* 10000001 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 2 0x02 '^B' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0xff, /* 11111111 */
+ 0xdb, /* 11011011 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xc3, /* 11000011 */
+ 0xe7, /* 11100111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 3 0x03 '^C' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x6c, /* 01101100 */
+ 0xfe, /* 11111110 */
+ 0xfe, /* 11111110 */
+ 0xfe, /* 11111110 */
+ 0xfe, /* 11111110 */
+ 0x7c, /* 01111100 */
+ 0x38, /* 00111000 */
+ 0x10, /* 00010000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 4 0x04 '^D' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x10, /* 00010000 */
+ 0x38, /* 00111000 */
+ 0x7c, /* 01111100 */
+ 0xfe, /* 11111110 */
+ 0x7c, /* 01111100 */
+ 0x38, /* 00111000 */
+ 0x10, /* 00010000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 5 0x05 '^E' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x3c, /* 00111100 */
+ 0xe7, /* 11100111 */
+ 0xe7, /* 11100111 */
+ 0xe7, /* 11100111 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 6 0x06 '^F' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x7e, /* 01111110 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 7 0x07 '^G' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 8 0x08 '^H' */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xe7, /* 11100111 */
+ 0xc3, /* 11000011 */
+ 0xc3, /* 11000011 */
+ 0xe7, /* 11100111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+
+ /* 9 0x09 '^I' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x3c, /* 00111100 */
+ 0x66, /* 01100110 */
+ 0x42, /* 01000010 */
+ 0x42, /* 01000010 */
+ 0x66, /* 01100110 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 10 0x0a '^J' */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xc3, /* 11000011 */
+ 0x99, /* 10011001 */
+ 0xbd, /* 10111101 */
+ 0xbd, /* 10111101 */
+ 0x99, /* 10011001 */
+ 0xc3, /* 11000011 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+
+ /* 11 0x0b '^K' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x1e, /* 00011110 */
+ 0x0e, /* 00001110 */
+ 0x1a, /* 00011010 */
+ 0x32, /* 00110010 */
+ 0x78, /* 01111000 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x78, /* 01111000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 12 0x0c '^L' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x3c, /* 00111100 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 13 0x0d '^M' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x3f, /* 00111111 */
+ 0x33, /* 00110011 */
+ 0x3f, /* 00111111 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x70, /* 01110000 */
+ 0xf0, /* 11110000 */
+ 0xe0, /* 11100000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 14 0x0e '^N' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7f, /* 01111111 */
+ 0x63, /* 01100011 */
+ 0x7f, /* 01111111 */
+ 0x63, /* 01100011 */
+ 0x63, /* 01100011 */
+ 0x63, /* 01100011 */
+ 0x63, /* 01100011 */
+ 0x67, /* 01100111 */
+ 0xe7, /* 11100111 */
+ 0xe6, /* 11100110 */
+ 0xc0, /* 11000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 15 0x0f '^O' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0xdb, /* 11011011 */
+ 0x3c, /* 00111100 */
+ 0xe7, /* 11100111 */
+ 0x3c, /* 00111100 */
+ 0xdb, /* 11011011 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 16 0x10 '^P' */
+ 0x00, /* 00000000 */
+ 0x80, /* 10000000 */
+ 0xc0, /* 11000000 */
+ 0xe0, /* 11100000 */
+ 0xf0, /* 11110000 */
+ 0xf8, /* 11111000 */
+ 0xfe, /* 11111110 */
+ 0xf8, /* 11111000 */
+ 0xf0, /* 11110000 */
+ 0xe0, /* 11100000 */
+ 0xc0, /* 11000000 */
+ 0x80, /* 10000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 17 0x11 '^Q' */
+ 0x00, /* 00000000 */
+ 0x02, /* 00000010 */
+ 0x06, /* 00000110 */
+ 0x0e, /* 00001110 */
+ 0x1e, /* 00011110 */
+ 0x3e, /* 00111110 */
+ 0xfe, /* 11111110 */
+ 0x3e, /* 00111110 */
+ 0x1e, /* 00011110 */
+ 0x0e, /* 00001110 */
+ 0x06, /* 00000110 */
+ 0x02, /* 00000010 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 18 0x12 '^R' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 19 0x13 '^S' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x00, /* 00000000 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 20 0x14 '^T' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7f, /* 01111111 */
+ 0xdb, /* 11011011 */
+ 0xdb, /* 11011011 */
+ 0xdb, /* 11011011 */
+ 0x7b, /* 01111011 */
+ 0x1b, /* 00011011 */
+ 0x1b, /* 00011011 */
+ 0x1b, /* 00011011 */
+ 0x1b, /* 00011011 */
+ 0x1b, /* 00011011 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 21 0x15 '^U' */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0x60, /* 01100000 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x6c, /* 01101100 */
+ 0x38, /* 00111000 */
+ 0x0c, /* 00001100 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 22 0x16 '^V' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0xfe, /* 11111110 */
+ 0xfe, /* 11111110 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 23 0x17 '^W' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 24 0x18 '^X' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 25 0x19 '^Y' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 26 0x1a '^Z' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x0c, /* 00001100 */
+ 0xfe, /* 11111110 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 27 0x1b '^[' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0xfe, /* 11111110 */
+ 0x60, /* 01100000 */
+ 0x30, /* 00110000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 28 0x1c '^\' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 29 0x1d '^]' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x28, /* 00101000 */
+ 0x6c, /* 01101100 */
+ 0xfe, /* 11111110 */
+ 0x6c, /* 01101100 */
+ 0x28, /* 00101000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 30 0x1e '^^' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x10, /* 00010000 */
+ 0x38, /* 00111000 */
+ 0x38, /* 00111000 */
+ 0x7c, /* 01111100 */
+ 0x7c, /* 01111100 */
+ 0xfe, /* 11111110 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 31 0x1f '^_' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0xfe, /* 11111110 */
+ 0x7c, /* 01111100 */
+ 0x7c, /* 01111100 */
+ 0x38, /* 00111000 */
+ 0x38, /* 00111000 */
+ 0x10, /* 00010000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 32 0x20 ' ' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 33 0x21 '!' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x3c, /* 00111100 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 34 0x22 '"' */
+ 0x00, /* 00000000 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x24, /* 00100100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 35 0x23 '#' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0xfe, /* 11111110 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0xfe, /* 11111110 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 36 0x24 '$' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc2, /* 11000010 */
+ 0xc0, /* 11000000 */
+ 0x7c, /* 01111100 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0x86, /* 10000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 37 0x25 '%' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc2, /* 11000010 */
+ 0xc6, /* 11000110 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0xc6, /* 11000110 */
+ 0x86, /* 10000110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 38 0x26 '&' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0x38, /* 00111000 */
+ 0x76, /* 01110110 */
+ 0xdc, /* 11011100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 39 0x27 ''' */
+ 0x00, /* 00000000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 40 0x28 '(' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x0c, /* 00001100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 41 0x29 ')' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 42 0x2a '*' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x66, /* 01100110 */
+ 0x3c, /* 00111100 */
+ 0xff, /* 11111111 */
+ 0x3c, /* 00111100 */
+ 0x66, /* 01100110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 43 0x2b '+' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 44 0x2c ',' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 45 0x2d '-' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 46 0x2e '.' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 47 0x2f '/' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x02, /* 00000010 */
+ 0x06, /* 00000110 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0xc0, /* 11000000 */
+ 0x80, /* 10000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 48 0x30 '0' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xd6, /* 11010110 */
+ 0xd6, /* 11010110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x6c, /* 01101100 */
+ 0x38, /* 00111000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 49 0x31 '1' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x38, /* 00111000 */
+ 0x78, /* 01111000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 50 0x32 '2' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0x06, /* 00000110 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0xc0, /* 11000000 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 51 0x33 '3' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0x3c, /* 00111100 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 52 0x34 '4' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x0c, /* 00001100 */
+ 0x1c, /* 00011100 */
+ 0x3c, /* 00111100 */
+ 0x6c, /* 01101100 */
+ 0xcc, /* 11001100 */
+ 0xfe, /* 11111110 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x1e, /* 00011110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 53 0x35 '5' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xfc, /* 11111100 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 54 0x36 '6' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x38, /* 00111000 */
+ 0x60, /* 01100000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xfc, /* 11111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 55 0x37 '7' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0xc6, /* 11000110 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 56 0x38 '8' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 57 0x39 '9' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7e, /* 01111110 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0x0c, /* 00001100 */
+ 0x78, /* 01111000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 58 0x3a ':' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 59 0x3b ';' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 60 0x3c '<' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x06, /* 00000110 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x0c, /* 00001100 */
+ 0x06, /* 00000110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 61 0x3d '=' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 62 0x3e '>' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x60, /* 01100000 */
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x0c, /* 00001100 */
+ 0x06, /* 00000110 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 63 0x3f '?' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 64 0x40 '@' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xde, /* 11011110 */
+ 0xde, /* 11011110 */
+ 0xde, /* 11011110 */
+ 0xdc, /* 11011100 */
+ 0xc0, /* 11000000 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 65 0x41 'A' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x10, /* 00010000 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 66 0x42 'B' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfc, /* 11111100 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x7c, /* 01111100 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0xfc, /* 11111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 67 0x43 'C' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x3c, /* 00111100 */
+ 0x66, /* 01100110 */
+ 0xc2, /* 11000010 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc2, /* 11000010 */
+ 0x66, /* 01100110 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 68 0x44 'D' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xf8, /* 11111000 */
+ 0x6c, /* 01101100 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x6c, /* 01101100 */
+ 0xf8, /* 11111000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 69 0x45 'E' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0x66, /* 01100110 */
+ 0x62, /* 01100010 */
+ 0x68, /* 01101000 */
+ 0x78, /* 01111000 */
+ 0x68, /* 01101000 */
+ 0x60, /* 01100000 */
+ 0x62, /* 01100010 */
+ 0x66, /* 01100110 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 70 0x46 'F' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0x66, /* 01100110 */
+ 0x62, /* 01100010 */
+ 0x68, /* 01101000 */
+ 0x78, /* 01111000 */
+ 0x68, /* 01101000 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0xf0, /* 11110000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 71 0x47 'G' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x3c, /* 00111100 */
+ 0x66, /* 01100110 */
+ 0xc2, /* 11000010 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xde, /* 11011110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x66, /* 01100110 */
+ 0x3a, /* 00111010 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 72 0x48 'H' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 73 0x49 'I' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 74 0x4a 'J' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x1e, /* 00011110 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x78, /* 01111000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 75 0x4b 'K' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xe6, /* 11100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x6c, /* 01101100 */
+ 0x78, /* 01111000 */
+ 0x78, /* 01111000 */
+ 0x6c, /* 01101100 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0xe6, /* 11100110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 76 0x4c 'L' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xf0, /* 11110000 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0x62, /* 01100010 */
+ 0x66, /* 01100110 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 77 0x4d 'M' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0xee, /* 11101110 */
+ 0xfe, /* 11111110 */
+ 0xfe, /* 11111110 */
+ 0xd6, /* 11010110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 78 0x4e 'N' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0xe6, /* 11100110 */
+ 0xf6, /* 11110110 */
+ 0xfe, /* 11111110 */
+ 0xde, /* 11011110 */
+ 0xce, /* 11001110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 79 0x4f 'O' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 80 0x50 'P' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfc, /* 11111100 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x7c, /* 01111100 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0xf0, /* 11110000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 81 0x51 'Q' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xd6, /* 11010110 */
+ 0xde, /* 11011110 */
+ 0x7c, /* 01111100 */
+ 0x0c, /* 00001100 */
+ 0x0e, /* 00001110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 82 0x52 'R' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfc, /* 11111100 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x7c, /* 01111100 */
+ 0x6c, /* 01101100 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0xe6, /* 11100110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 83 0x53 'S' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x60, /* 01100000 */
+ 0x38, /* 00111000 */
+ 0x0c, /* 00001100 */
+ 0x06, /* 00000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 84 0x54 'T' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0x7e, /* 01111110 */
+ 0x5a, /* 01011010 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 85 0x55 'U' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 86 0x56 'V' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x6c, /* 01101100 */
+ 0x38, /* 00111000 */
+ 0x10, /* 00010000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 87 0x57 'W' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xd6, /* 11010110 */
+ 0xd6, /* 11010110 */
+ 0xd6, /* 11010110 */
+ 0xfe, /* 11111110 */
+ 0xee, /* 11101110 */
+ 0x6c, /* 01101100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 88 0x58 'X' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x6c, /* 01101100 */
+ 0x7c, /* 01111100 */
+ 0x38, /* 00111000 */
+ 0x38, /* 00111000 */
+ 0x7c, /* 01111100 */
+ 0x6c, /* 01101100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 89 0x59 'Y' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 90 0x5a 'Z' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0xc6, /* 11000110 */
+ 0x86, /* 10000110 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0xc2, /* 11000010 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 91 0x5b '[' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x3c, /* 00111100 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 92 0x5c '\' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x80, /* 10000000 */
+ 0xc0, /* 11000000 */
+ 0xe0, /* 11100000 */
+ 0x70, /* 01110000 */
+ 0x38, /* 00111000 */
+ 0x1c, /* 00011100 */
+ 0x0e, /* 00001110 */
+ 0x06, /* 00000110 */
+ 0x02, /* 00000010 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 93 0x5d ']' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x3c, /* 00111100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 94 0x5e '^' */
+ 0x10, /* 00010000 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 95 0x5f '_' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 96 0x60 '`' */
+ 0x00, /* 00000000 */
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x0c, /* 00001100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 97 0x61 'a' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x78, /* 01111000 */
+ 0x0c, /* 00001100 */
+ 0x7c, /* 01111100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 98 0x62 'b' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xe0, /* 11100000 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0x78, /* 01111000 */
+ 0x6c, /* 01101100 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 99 0x63 'c' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 100 0x64 'd' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x1c, /* 00011100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x3c, /* 00111100 */
+ 0x6c, /* 01101100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 101 0x65 'e' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 102 0x66 'f' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x1c, /* 00011100 */
+ 0x36, /* 00110110 */
+ 0x32, /* 00110010 */
+ 0x30, /* 00110000 */
+ 0x78, /* 01111000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x78, /* 01111000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 103 0x67 'g' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x76, /* 01110110 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x7c, /* 01111100 */
+ 0x0c, /* 00001100 */
+ 0xcc, /* 11001100 */
+ 0x78, /* 01111000 */
+ 0x00, /* 00000000 */
+
+ /* 104 0x68 'h' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xe0, /* 11100000 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0x6c, /* 01101100 */
+ 0x76, /* 01110110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0xe6, /* 11100110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 105 0x69 'i' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x38, /* 00111000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 106 0x6a 'j' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0x00, /* 00000000 */
+ 0x0e, /* 00001110 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+
+ /* 107 0x6b 'k' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xe0, /* 11100000 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0x66, /* 01100110 */
+ 0x6c, /* 01101100 */
+ 0x78, /* 01111000 */
+ 0x78, /* 01111000 */
+ 0x6c, /* 01101100 */
+ 0x66, /* 01100110 */
+ 0xe6, /* 11100110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 108 0x6c 'l' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x38, /* 00111000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 109 0x6d 'm' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xec, /* 11101100 */
+ 0xfe, /* 11111110 */
+ 0xd6, /* 11010110 */
+ 0xd6, /* 11010110 */
+ 0xd6, /* 11010110 */
+ 0xd6, /* 11010110 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 110 0x6e 'n' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xdc, /* 11011100 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 111 0x6f 'o' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 112 0x70 'p' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xdc, /* 11011100 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x7c, /* 01111100 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0xf0, /* 11110000 */
+ 0x00, /* 00000000 */
+
+ /* 113 0x71 'q' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x76, /* 01110110 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x7c, /* 01111100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x1e, /* 00011110 */
+ 0x00, /* 00000000 */
+
+ /* 114 0x72 'r' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xdc, /* 11011100 */
+ 0x76, /* 01110110 */
+ 0x66, /* 01100110 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0xf0, /* 11110000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 115 0x73 's' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0x60, /* 01100000 */
+ 0x38, /* 00111000 */
+ 0x0c, /* 00001100 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 116 0x74 't' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x10, /* 00010000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0xfc, /* 11111100 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x36, /* 00110110 */
+ 0x1c, /* 00011100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 117 0x75 'u' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 118 0x76 'v' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x6c, /* 01101100 */
+ 0x38, /* 00111000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 119 0x77 'w' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xd6, /* 11010110 */
+ 0xd6, /* 11010110 */
+ 0xd6, /* 11010110 */
+ 0xfe, /* 11111110 */
+ 0x6c, /* 01101100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 120 0x78 'x' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0x6c, /* 01101100 */
+ 0x38, /* 00111000 */
+ 0x38, /* 00111000 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 121 0x79 'y' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7e, /* 01111110 */
+ 0x06, /* 00000110 */
+ 0x0c, /* 00001100 */
+ 0xf8, /* 11111000 */
+ 0x00, /* 00000000 */
+
+ /* 122 0x7a 'z' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0xcc, /* 11001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 123 0x7b '{' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x0e, /* 00001110 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x70, /* 01110000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x0e, /* 00001110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 124 0x7c '|' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 125 0x7d '}' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x70, /* 01110000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x0e, /* 00001110 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x70, /* 01110000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 126 0x7e '~' */
+ 0x00, /* 00000000 */
+ 0x76, /* 01110110 */
+ 0xdc, /* 11011100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 127 0x7f '\7f' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x10, /* 00010000 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 128 0x80 '\80' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x3c, /* 00111100 */
+ 0x66, /* 01100110 */
+ 0xc2, /* 11000010 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc2, /* 11000010 */
+ 0x66, /* 01100110 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x70, /* 01110000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 129 0x81 '\81' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xcc, /* 11001100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 130 0x82 '\82' */
+ 0x00, /* 00000000 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 131 0x83 '\83' */
+ 0x00, /* 00000000 */
+ 0x10, /* 00010000 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0x00, /* 00000000 */
+ 0x78, /* 01111000 */
+ 0x0c, /* 00001100 */
+ 0x7c, /* 01111100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 132 0x84 '\84' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xcc, /* 11001100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x78, /* 01111000 */
+ 0x0c, /* 00001100 */
+ 0x7c, /* 01111100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 133 0x85 '\85' */
+ 0x00, /* 00000000 */
+ 0x60, /* 01100000 */
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x78, /* 01111000 */
+ 0x0c, /* 00001100 */
+ 0x7c, /* 01111100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 134 0x86 '\86' */
+ 0x00, /* 00000000 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0x38, /* 00111000 */
+ 0x00, /* 00000000 */
+ 0x78, /* 01111000 */
+ 0x0c, /* 00001100 */
+ 0x7c, /* 01111100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 135 0x87 '\87' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x18, /* 00011000 */
+ 0x70, /* 01110000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 136 0x88 '\88' */
+ 0x00, /* 00000000 */
+ 0x10, /* 00010000 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 137 0x89 '\89' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 138 0x8a '\8a' */
+ 0x00, /* 00000000 */
+ 0x60, /* 01100000 */
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 139 0x8b '\8b' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x66, /* 01100110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x38, /* 00111000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 140 0x8c '\8c' */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x66, /* 01100110 */
+ 0x00, /* 00000000 */
+ 0x38, /* 00111000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 141 0x8d '\8d' */
+ 0x00, /* 00000000 */
+ 0x60, /* 01100000 */
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x38, /* 00111000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 142 0x8e '\8e' */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0x10, /* 00010000 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 143 0x8f '\8f' */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0x38, /* 00111000 */
+ 0x10, /* 00010000 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 144 0x90 '\90' */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0x66, /* 01100110 */
+ 0x62, /* 01100010 */
+ 0x68, /* 01101000 */
+ 0x78, /* 01111000 */
+ 0x68, /* 01101000 */
+ 0x62, /* 01100010 */
+ 0x66, /* 01100110 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 145 0x91 '\91' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xec, /* 11101100 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x7e, /* 01111110 */
+ 0xd8, /* 11011000 */
+ 0xd8, /* 11011000 */
+ 0x6e, /* 01101110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 146 0x92 '\92' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x3e, /* 00111110 */
+ 0x6c, /* 01101100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xfe, /* 11111110 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xce, /* 11001110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 147 0x93 '\93' */
+ 0x00, /* 00000000 */
+ 0x10, /* 00010000 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 148 0x94 '\94' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 149 0x95 '\95' */
+ 0x00, /* 00000000 */
+ 0x60, /* 01100000 */
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 150 0x96 '\96' */
+ 0x00, /* 00000000 */
+ 0x30, /* 00110000 */
+ 0x78, /* 01111000 */
+ 0xcc, /* 11001100 */
+ 0x00, /* 00000000 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 151 0x97 '\97' */
+ 0x00, /* 00000000 */
+ 0x60, /* 01100000 */
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 152 0x98 '\98' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7e, /* 01111110 */
+ 0x06, /* 00000110 */
+ 0x0c, /* 00001100 */
+ 0x78, /* 01111000 */
+ 0x00, /* 00000000 */
+
+ /* 153 0x99 '\99' */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 154 0x9a '\9a' */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 155 0x9b '\9b' */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 156 0x9c '\9c' */
+ 0x00, /* 00000000 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0x64, /* 01100100 */
+ 0x60, /* 01100000 */
+ 0xf0, /* 11110000 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0xe6, /* 11100110 */
+ 0xfc, /* 11111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 157 0x9d '\9d' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 158 0x9e '\9e' */
+ 0x00, /* 00000000 */
+ 0xf8, /* 11111000 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xf8, /* 11111000 */
+ 0xc4, /* 11000100 */
+ 0xcc, /* 11001100 */
+ 0xde, /* 11011110 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 159 0x9f '\9f' */
+ 0x00, /* 00000000 */
+ 0x0e, /* 00001110 */
+ 0x1b, /* 00011011 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0xd8, /* 11011000 */
+ 0x70, /* 01110000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 160 0xa0 ' ' */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0x00, /* 00000000 */
+ 0x78, /* 01111000 */
+ 0x0c, /* 00001100 */
+ 0x7c, /* 01111100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 161 0xa1 '¡' */
+ 0x00, /* 00000000 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x00, /* 00000000 */
+ 0x38, /* 00111000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 162 0xa2 '¢' */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 163 0xa3 '£' */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0x00, /* 00000000 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0x76, /* 01110110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 164 0xa4 '¤' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x76, /* 01110110 */
+ 0xdc, /* 11011100 */
+ 0x00, /* 00000000 */
+ 0xdc, /* 11011100 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 165 0xa5 '¥' */
+ 0x76, /* 01110110 */
+ 0xdc, /* 11011100 */
+ 0x00, /* 00000000 */
+ 0xc6, /* 11000110 */
+ 0xe6, /* 11100110 */
+ 0xf6, /* 11110110 */
+ 0xfe, /* 11111110 */
+ 0xde, /* 11011110 */
+ 0xce, /* 11001110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 166 0xa6 '¦' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x3c, /* 00111100 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0x3e, /* 00111110 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 167 0xa7 '§' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0x38, /* 00111000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 168 0xa8 '¨' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x00, /* 00000000 */
+ 0x30, /* 00110000 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0xc0, /* 11000000 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x7c, /* 01111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 169 0xa9 '©' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 170 0xaa 'ª' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 171 0xab '«' */
+ 0x00, /* 00000000 */
+ 0x60, /* 01100000 */
+ 0xe0, /* 11100000 */
+ 0x62, /* 01100010 */
+ 0x66, /* 01100110 */
+ 0x6c, /* 01101100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0xdc, /* 11011100 */
+ 0x86, /* 10000110 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x3e, /* 00111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 172 0xac '¬' */
+ 0x00, /* 00000000 */
+ 0x60, /* 01100000 */
+ 0xe0, /* 11100000 */
+ 0x62, /* 01100010 */
+ 0x66, /* 01100110 */
+ 0x6c, /* 01101100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x66, /* 01100110 */
+ 0xce, /* 11001110 */
+ 0x9a, /* 10011010 */
+ 0x3f, /* 00111111 */
+ 0x06, /* 00000110 */
+ 0x06, /* 00000110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 173 0xad '' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x3c, /* 00111100 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 174 0xae '®' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x36, /* 00110110 */
+ 0x6c, /* 01101100 */
+ 0xd8, /* 11011000 */
+ 0x6c, /* 01101100 */
+ 0x36, /* 00110110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 175 0xaf '¯' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xd8, /* 11011000 */
+ 0x6c, /* 01101100 */
+ 0x36, /* 00110110 */
+ 0x6c, /* 01101100 */
+ 0xd8, /* 11011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 176 0xb0 '°' */
+ 0x11, /* 00010001 */
+ 0x44, /* 01000100 */
+ 0x11, /* 00010001 */
+ 0x44, /* 01000100 */
+ 0x11, /* 00010001 */
+ 0x44, /* 01000100 */
+ 0x11, /* 00010001 */
+ 0x44, /* 01000100 */
+ 0x11, /* 00010001 */
+ 0x44, /* 01000100 */
+ 0x11, /* 00010001 */
+ 0x44, /* 01000100 */
+ 0x11, /* 00010001 */
+ 0x44, /* 01000100 */
+ 0x11, /* 00010001 */
+ 0x44, /* 01000100 */
+
+ /* 177 0xb1 '±' */
+ 0x55, /* 01010101 */
+ 0xaa, /* 10101010 */
+ 0x55, /* 01010101 */
+ 0xaa, /* 10101010 */
+ 0x55, /* 01010101 */
+ 0xaa, /* 10101010 */
+ 0x55, /* 01010101 */
+ 0xaa, /* 10101010 */
+ 0x55, /* 01010101 */
+ 0xaa, /* 10101010 */
+ 0x55, /* 01010101 */
+ 0xaa, /* 10101010 */
+ 0x55, /* 01010101 */
+ 0xaa, /* 10101010 */
+ 0x55, /* 01010101 */
+ 0xaa, /* 10101010 */
+
+ /* 178 0xb2 '²' */
+ 0xdd, /* 11011101 */
+ 0x77, /* 01110111 */
+ 0xdd, /* 11011101 */
+ 0x77, /* 01110111 */
+ 0xdd, /* 11011101 */
+ 0x77, /* 01110111 */
+ 0xdd, /* 11011101 */
+ 0x77, /* 01110111 */
+ 0xdd, /* 11011101 */
+ 0x77, /* 01110111 */
+ 0xdd, /* 11011101 */
+ 0x77, /* 01110111 */
+ 0xdd, /* 11011101 */
+ 0x77, /* 01110111 */
+ 0xdd, /* 11011101 */
+ 0x77, /* 01110111 */
+
+ /* 179 0xb3 '³' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+
+ /* 180 0xb4 '´' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0xf8, /* 11111000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+
+ /* 181 0xb5 'µ' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0xf8, /* 11111000 */
+ 0x18, /* 00011000 */
+ 0xf8, /* 11111000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+
+ /* 182 0xb6 '¶' */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0xf6, /* 11110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+
+ /* 183 0xb7 '·' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+
+ /* 184 0xb8 '¸' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xf8, /* 11111000 */
+ 0x18, /* 00011000 */
+ 0xf8, /* 11111000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+
+ /* 185 0xb9 '¹' */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0xf6, /* 11110110 */
+ 0x06, /* 00000110 */
+ 0xf6, /* 11110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+
+ /* 186 0xba 'º' */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+
+ /* 187 0xbb '»' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0x06, /* 00000110 */
+ 0xf6, /* 11110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+
+ /* 188 0xbc '¼' */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0xf6, /* 11110110 */
+ 0x06, /* 00000110 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 189 0xbd '½' */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 190 0xbe '¾' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0xf8, /* 11111000 */
+ 0x18, /* 00011000 */
+ 0xf8, /* 11111000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 191 0xbf '¿' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xf8, /* 11111000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+
+ /* 192 0xc0 'À' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x1f, /* 00011111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 193 0xc1 'Á' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 194 0xc2 'Â' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+
+ /* 195 0xc3 'Ã' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x1f, /* 00011111 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+
+ /* 196 0xc4 'Ä' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 197 0xc5 'Å' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0xff, /* 11111111 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+
+ /* 198 0xc6 'Æ' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x1f, /* 00011111 */
+ 0x18, /* 00011000 */
+ 0x1f, /* 00011111 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+
+ /* 199 0xc7 'Ç' */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x37, /* 00110111 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+
+ /* 200 0xc8 'È' */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x37, /* 00110111 */
+ 0x30, /* 00110000 */
+ 0x3f, /* 00111111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 201 0xc9 'É' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x3f, /* 00111111 */
+ 0x30, /* 00110000 */
+ 0x37, /* 00110111 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+
+ /* 202 0xca 'Ê' */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0xf7, /* 11110111 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 203 0xcb 'Ë' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0xf7, /* 11110111 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+
+ /* 204 0xcc 'Ì' */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x37, /* 00110111 */
+ 0x30, /* 00110000 */
+ 0x37, /* 00110111 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+
+ /* 205 0xcd 'Í' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 206 0xce 'Î' */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0xf7, /* 11110111 */
+ 0x00, /* 00000000 */
+ 0xf7, /* 11110111 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+
+ /* 207 0xcf 'Ï' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 208 0xd0 'Ð' */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 209 0xd1 'Ñ' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+
+ /* 210 0xd2 'Ò' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+
+ /* 211 0xd3 'Ó' */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x3f, /* 00111111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 212 0xd4 'Ô' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x1f, /* 00011111 */
+ 0x18, /* 00011000 */
+ 0x1f, /* 00011111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 213 0xd5 'Õ' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x1f, /* 00011111 */
+ 0x18, /* 00011000 */
+ 0x1f, /* 00011111 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+
+ /* 214 0xd6 'Ö' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x3f, /* 00111111 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+
+ /* 215 0xd7 '×' */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0xff, /* 11111111 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+
+ /* 216 0xd8 'Ø' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0xff, /* 11111111 */
+ 0x18, /* 00011000 */
+ 0xff, /* 11111111 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+
+ /* 217 0xd9 'Ù' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0xf8, /* 11111000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 218 0xda 'Ú' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x1f, /* 00011111 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+
+ /* 219 0xdb 'Û' */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+
+ /* 220 0xdc 'Ü' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+
+ /* 221 0xdd 'Ý' */
+ 0xf0, /* 11110000 */
+ 0xf0, /* 11110000 */
+ 0xf0, /* 11110000 */
+ 0xf0, /* 11110000 */
+ 0xf0, /* 11110000 */
+ 0xf0, /* 11110000 */
+ 0xf0, /* 11110000 */
+ 0xf0, /* 11110000 */
+ 0xf0, /* 11110000 */
+ 0xf0, /* 11110000 */
+ 0xf0, /* 11110000 */
+ 0xf0, /* 11110000 */
+ 0xf0, /* 11110000 */
+ 0xf0, /* 11110000 */
+ 0xf0, /* 11110000 */
+ 0xf0, /* 11110000 */
+
+ /* 222 0xde 'Þ' */
+ 0x0f, /* 00001111 */
+ 0x0f, /* 00001111 */
+ 0x0f, /* 00001111 */
+ 0x0f, /* 00001111 */
+ 0x0f, /* 00001111 */
+ 0x0f, /* 00001111 */
+ 0x0f, /* 00001111 */
+ 0x0f, /* 00001111 */
+ 0x0f, /* 00001111 */
+ 0x0f, /* 00001111 */
+ 0x0f, /* 00001111 */
+ 0x0f, /* 00001111 */
+ 0x0f, /* 00001111 */
+ 0x0f, /* 00001111 */
+ 0x0f, /* 00001111 */
+ 0x0f, /* 00001111 */
+
+ /* 223 0xdf 'ß' */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0xff, /* 11111111 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 224 0xe0 'à' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x76, /* 01110110 */
+ 0xdc, /* 11011100 */
+ 0xd8, /* 11011000 */
+ 0xd8, /* 11011000 */
+ 0xd8, /* 11011000 */
+ 0xdc, /* 11011100 */
+ 0x76, /* 01110110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 225 0xe1 'á' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x78, /* 01111000 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xcc, /* 11001100 */
+ 0xd8, /* 11011000 */
+ 0xcc, /* 11001100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xcc, /* 11001100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 226 0xe2 'â' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0xc0, /* 11000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 227 0xe3 'ã' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 228 0xe4 'ä' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0xc6, /* 11000110 */
+ 0x60, /* 01100000 */
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 229 0xe5 'å' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0xd8, /* 11011000 */
+ 0xd8, /* 11011000 */
+ 0xd8, /* 11011000 */
+ 0xd8, /* 11011000 */
+ 0xd8, /* 11011000 */
+ 0x70, /* 01110000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 230 0xe6 'æ' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x7c, /* 01111100 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0xc0, /* 11000000 */
+ 0x00, /* 00000000 */
+
+ /* 231 0xe7 'ç' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x76, /* 01110110 */
+ 0xdc, /* 11011100 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 232 0xe8 'è' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x3c, /* 00111100 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x3c, /* 00111100 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 233 0xe9 'é' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xfe, /* 11111110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x6c, /* 01101100 */
+ 0x38, /* 00111000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 234 0xea 'ê' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0xee, /* 11101110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 235 0xeb 'ë' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x1e, /* 00011110 */
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x0c, /* 00001100 */
+ 0x3e, /* 00111110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x66, /* 01100110 */
+ 0x3c, /* 00111100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 236 0xec 'ì' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0xdb, /* 11011011 */
+ 0xdb, /* 11011011 */
+ 0xdb, /* 11011011 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 237 0xed 'í' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x03, /* 00000011 */
+ 0x06, /* 00000110 */
+ 0x7e, /* 01111110 */
+ 0xdb, /* 11011011 */
+ 0xdb, /* 11011011 */
+ 0xf3, /* 11110011 */
+ 0x7e, /* 01111110 */
+ 0x60, /* 01100000 */
+ 0xc0, /* 11000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 238 0xee 'î' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x1c, /* 00011100 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0x7c, /* 01111100 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0x60, /* 01100000 */
+ 0x30, /* 00110000 */
+ 0x1c, /* 00011100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 239 0xef 'ï' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7c, /* 01111100 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0xc6, /* 11000110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 240 0xf0 'ð' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0xfe, /* 11111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 241 0xf1 'ñ' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x7e, /* 01111110 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 242 0xf2 'ò' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x0c, /* 00001100 */
+ 0x06, /* 00000110 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 243 0xf3 'ó' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x30, /* 00110000 */
+ 0x60, /* 01100000 */
+ 0x30, /* 00110000 */
+ 0x18, /* 00011000 */
+ 0x0c, /* 00001100 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 244 0xf4 'ô' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x0e, /* 00001110 */
+ 0x1b, /* 00011011 */
+ 0x1b, /* 00011011 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+
+ /* 245 0xf5 'õ' */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0xd8, /* 11011000 */
+ 0xd8, /* 11011000 */
+ 0xd8, /* 11011000 */
+ 0x70, /* 01110000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 246 0xf6 'ö' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 247 0xf7 '÷' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x76, /* 01110110 */
+ 0xdc, /* 11011100 */
+ 0x00, /* 00000000 */
+ 0x76, /* 01110110 */
+ 0xdc, /* 11011100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 248 0xf8 'ø' */
+ 0x00, /* 00000000 */
+ 0x38, /* 00111000 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0x38, /* 00111000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 249 0xf9 'ù' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 250 0xfa 'ú' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x18, /* 00011000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 251 0xfb 'û' */
+ 0x00, /* 00000000 */
+ 0x0f, /* 00001111 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0x0c, /* 00001100 */
+ 0xec, /* 11101100 */
+ 0x6c, /* 01101100 */
+ 0x6c, /* 01101100 */
+ 0x3c, /* 00111100 */
+ 0x1c, /* 00011100 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 252 0xfc 'ü' */
+ 0x00, /* 00000000 */
+ 0x6c, /* 01101100 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x36, /* 00110110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 253 0xfd 'ý' */
+ 0x00, /* 00000000 */
+ 0x3c, /* 00111100 */
+ 0x66, /* 01100110 */
+ 0x0c, /* 00001100 */
+ 0x18, /* 00011000 */
+ 0x32, /* 00110010 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 254 0xfe 'þ' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x7e, /* 01111110 */
+ 0x7e, /* 01111110 */
+ 0x7e, /* 01111110 */
+ 0x7e, /* 01111110 */
+ 0x7e, /* 01111110 */
+ 0x7e, /* 01111110 */
+ 0x7e, /* 01111110 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+ /* 255 0xff 'ÿ' */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+ 0x00, /* 00000000 */
+
+};
--- /dev/null
+/*
+ * QEMU System Emulator
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <time.h>
+#include <errno.h>
+#include <sys/time.h>
+
+#ifndef _WIN32
+#include <sys/times.h>
+#include <sys/wait.h>
+#include <termios.h>
+#include <sys/poll.h>
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <dirent.h>
+#ifdef _BSD
+#include <sys/stat.h>
+#ifndef __APPLE__
+#include <libutil.h>
+#endif
+#else
+#include <linux/if.h>
+#include <linux/if_tun.h>
+#include <pty.h>
+#include <malloc.h>
+#include <linux/rtc.h>
+#endif
+#endif
+
+#if defined(CONFIG_SLIRP)
+#include "libslirp.h"
+#endif
+
+#ifdef _WIN32
+#include <malloc.h>
+#include <sys/timeb.h>
+#include <windows.h>
+#define getopt_long_only getopt_long
+#define memalign(align, size) malloc(size)
+#endif
+
+#ifdef CONFIG_SDL
+#ifdef __APPLE__
+#include <SDL/SDL.h>
+#endif
+#endif /* CONFIG_SDL */
+
+#include "xc.h"
+#include "exec-all.h"
+
+//#define DO_TB_FLUSH
+
+#define DEFAULT_NETWORK_SCRIPT "/etc/xen/qemu-ifup"
+
+#if !defined(CONFIG_SOFTMMU)
+#define PHYS_RAM_MAX_SIZE (256 * 1024 * 1024)
+#else
+#define PHYS_RAM_MAX_SIZE (2047 * 1024 * 1024)
+#endif
+
+#ifdef TARGET_PPC
+#define DEFAULT_RAM_SIZE 144
+#else
+#define DEFAULT_RAM_SIZE 128
+#endif
+/* in ms */
+#define GUI_REFRESH_INTERVAL 30
+#define POLLING_INTERVAL 5
+
+/* XXX: use a two level table to limit memory usage */
+#define MAX_IOPORTS 65536
+
+const char *bios_dir = CONFIG_QEMU_SHAREDIR;
+char phys_ram_file[1024];
+CPUState *global_env;
+CPUState *cpu_single_env;
+void *ioport_opaque[MAX_IOPORTS];
+IOPortReadFunc *ioport_read_table[3][MAX_IOPORTS];
+IOPortWriteFunc *ioport_write_table[3][MAX_IOPORTS];
+BlockDriverState *bs_table[MAX_DISKS], *fd_table[MAX_FD];
+int vga_ram_size;
+int bios_size;
+static DisplayState display_state;
+int nographic;
+int usevnc; /* 1=vnc only, 2=vnc and sdl */
+const char* keyboard_layout = 0;
+int64_t ticks_per_sec;
+int boot_device = 'c';
+int ram_size;
+int domid;
+static char network_script[1024];
+int pit_min_timer_count = 0;
+int nb_nics;
+NetDriverState nd_table[MAX_NICS];
+QEMUTimer *gui_timer;
+QEMUTimer *polling_timer;
+int vm_running;
+int audio_enabled = 0;
+int sb16_enabled = 1;
+int adlib_enabled = 1;
+int gus_enabled = 1;
+int pci_enabled = 1;
+int prep_enabled = 0;
+int rtc_utc = 1;
+int cirrus_vga_enabled = 1;
+int graphic_width = 800;
+int graphic_height = 600;
+int graphic_depth = 15;
+int full_screen = 0;
+TextConsole *vga_console;
+CharDriverState *serial_hds[MAX_SERIAL_PORTS];
+int xc_handle;
+
+/***********************************************************/
+/* x86 ISA bus support */
+
+target_phys_addr_t isa_mem_base = 0;
+
+uint32_t default_ioport_readb(void *opaque, uint32_t address)
+{
+#ifdef DEBUG_UNUSED_IOPORT
+ fprintf(stderr, "inb: port=0x%04x\n", address);
+#endif
+ return 0xff;
+}
+
+void default_ioport_writeb(void *opaque, uint32_t address, uint32_t data)
+{
+#ifdef DEBUG_UNUSED_IOPORT
+ fprintf(stderr, "outb: port=0x%04x data=0x%02x\n", address, data);
+#endif
+}
+
+/* default is to make two byte accesses */
+uint32_t default_ioport_readw(void *opaque, uint32_t address)
+{
+ uint32_t data;
+ data = ioport_read_table[0][address](ioport_opaque[address], address);
+ address = (address + 1) & (MAX_IOPORTS - 1);
+ data |= ioport_read_table[0][address](ioport_opaque[address], address) << 8;
+ return data;
+}
+
+void default_ioport_writew(void *opaque, uint32_t address, uint32_t data)
+{
+ ioport_write_table[0][address](ioport_opaque[address], address, data & 0xff);
+ address = (address + 1) & (MAX_IOPORTS - 1);
+ ioport_write_table[0][address](ioport_opaque[address], address, (data >> 8) & 0xff);
+}
+
+uint32_t default_ioport_readl(void *opaque, uint32_t address)
+{
+#ifdef DEBUG_UNUSED_IOPORT
+ fprintf(stderr, "inl: port=0x%04x\n", address);
+#endif
+ return 0xffffffff;
+}
+
+void default_ioport_writel(void *opaque, uint32_t address, uint32_t data)
+{
+#ifdef DEBUG_UNUSED_IOPORT
+ fprintf(stderr, "outl: port=0x%04x data=0x%02x\n", address, data);
+#endif
+}
+
+void init_ioports(void)
+{
+ int i;
+
+ for(i = 0; i < MAX_IOPORTS; i++) {
+ ioport_read_table[0][i] = default_ioport_readb;
+ ioport_write_table[0][i] = default_ioport_writeb;
+ ioport_read_table[1][i] = default_ioport_readw;
+ ioport_write_table[1][i] = default_ioport_writew;
+ ioport_read_table[2][i] = default_ioport_readl;
+ ioport_write_table[2][i] = default_ioport_writel;
+ }
+}
+
+/* size is the word size in byte */
+int register_ioport_read(int start, int length, int size,
+ IOPortReadFunc *func, void *opaque)
+{
+ int i, bsize;
+
+ if (size == 1) {
+ bsize = 0;
+ } else if (size == 2) {
+ bsize = 1;
+ } else if (size == 4) {
+ bsize = 2;
+ } else {
+ hw_error("register_ioport_read: invalid size");
+ return -1;
+ }
+ for(i = start; i < start + length; i += size) {
+ ioport_read_table[bsize][i] = func;
+ if (ioport_opaque[i] != NULL && ioport_opaque[i] != opaque)
+ hw_error("register_ioport_read: invalid opaque");
+ ioport_opaque[i] = opaque;
+ }
+ return 0;
+}
+
+/* size is the word size in byte */
+int register_ioport_write(int start, int length, int size,
+ IOPortWriteFunc *func, void *opaque)
+{
+ int i, bsize;
+
+ if (size == 1) {
+ bsize = 0;
+ } else if (size == 2) {
+ bsize = 1;
+ } else if (size == 4) {
+ bsize = 2;
+ } else {
+ hw_error("register_ioport_write: invalid size");
+ return -1;
+ }
+ for(i = start; i < start + length; i += size) {
+ ioport_write_table[bsize][i] = func;
+ if (ioport_opaque[i] != NULL && ioport_opaque[i] != opaque)
+ hw_error("register_ioport_read: invalid opaque");
+ ioport_opaque[i] = opaque;
+ }
+ return 0;
+}
+
+void isa_unassign_ioport(int start, int length)
+{
+ int i;
+
+ for(i = start; i < start + length; i++) {
+ ioport_read_table[0][i] = default_ioport_readb;
+ ioport_read_table[1][i] = default_ioport_readw;
+ ioport_read_table[2][i] = default_ioport_readl;
+
+ ioport_write_table[0][i] = default_ioport_writeb;
+ ioport_write_table[1][i] = default_ioport_writew;
+ ioport_write_table[2][i] = default_ioport_writel;
+ }
+}
+
+void pstrcpy(char *buf, int buf_size, const char *str)
+{
+ int c;
+ char *q = buf;
+
+ if (buf_size <= 0)
+ return;
+
+ for(;;) {
+ c = *str++;
+ if (c == 0 || q >= buf + buf_size - 1)
+ break;
+ *q++ = c;
+ }
+ *q = '\0';
+}
+
+/* strcat and truncate. */
+char *pstrcat(char *buf, int buf_size, const char *s)
+{
+ int len;
+ len = strlen(buf);
+ if (len < buf_size)
+ pstrcpy(buf + len, buf_size - len, s);
+ return buf;
+}
+
+int strstart(const char *str, const char *val, const char **ptr)
+{
+ const char *p, *q;
+ p = str;
+ q = val;
+ while (*q != '\0') {
+ if (*p != *q)
+ return 0;
+ p++;
+ q++;
+ }
+ if (ptr)
+ *ptr = p;
+ return 1;
+}
+
+/* return the size or -1 if error */
+int get_image_size(const char *filename)
+{
+ int fd, size;
+ fd = open(filename, O_RDONLY | O_BINARY);
+ if (fd < 0)
+ return -1;
+ size = lseek(fd, 0, SEEK_END);
+ close(fd);
+ return size;
+}
+
+/* return the size or -1 if error */
+int load_image(const char *filename, uint8_t *addr)
+{
+ int fd, size;
+ fd = open(filename, O_RDONLY | O_BINARY);
+ if (fd < 0)
+ return -1;
+ size = lseek(fd, 0, SEEK_END);
+ lseek(fd, 0, SEEK_SET);
+ if (read(fd, addr, size) != size) {
+ close(fd);
+ return -1;
+ }
+ close(fd);
+ return size;
+}
+
+void cpu_outb(CPUState *env, int addr, int val)
+{
+#ifdef DEBUG_IOPORT
+ if (loglevel & CPU_LOG_IOPORT)
+ fprintf(logfile, "outb: %04x %02x\n", addr, val);
+#endif
+ ioport_write_table[0][addr](ioport_opaque[addr], addr, val);
+}
+
+void cpu_outw(CPUState *env, int addr, int val)
+{
+#ifdef DEBUG_IOPORT
+ if (loglevel & CPU_LOG_IOPORT)
+ fprintf(logfile, "outw: %04x %04x\n", addr, val);
+#endif
+ ioport_write_table[1][addr](ioport_opaque[addr], addr, val);
+}
+
+void cpu_outl(CPUState *env, int addr, int val)
+{
+#ifdef DEBUG_IOPORT
+ if (loglevel & CPU_LOG_IOPORT)
+ fprintf(logfile, "outl: %04x %08x\n", addr, val);
+#endif
+ ioport_write_table[2][addr](ioport_opaque[addr], addr, val);
+}
+
+int cpu_inb(CPUState *env, int addr)
+{
+ int val;
+ val = ioport_read_table[0][addr](ioport_opaque[addr], addr);
+#ifdef DEBUG_IOPORT
+ if (loglevel & CPU_LOG_IOPORT)
+ fprintf(logfile, "inb : %04x %02x\n", addr, val);
+#endif
+ return val;
+}
+
+int cpu_inw(CPUState *env, int addr)
+{
+ int val;
+ val = ioport_read_table[1][addr](ioport_opaque[addr], addr);
+#ifdef DEBUG_IOPORT
+ if (loglevel & CPU_LOG_IOPORT)
+ fprintf(logfile, "inw : %04x %04x\n", addr, val);
+#endif
+ return val;
+}
+
+int cpu_inl(CPUState *env, int addr)
+{
+ int val;
+ val = ioport_read_table[2][addr](ioport_opaque[addr], addr);
+#ifdef DEBUG_IOPORT
+ if (loglevel & CPU_LOG_IOPORT)
+ fprintf(logfile, "inl : %04x %08x\n", addr, val);
+#endif
+ return val;
+}
+
+/***********************************************************/
+void hw_error(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ fprintf(stderr, "qemu: hardware error: ");
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, "\n");
+ va_end(ap);
+ abort();
+}
+
+/***********************************************************/
+/* keyboard/mouse */
+
+static QEMUPutKBDEvent *qemu_put_kbd_event;
+static void *qemu_put_kbd_event_opaque;
+static QEMUPutMouseEvent *qemu_put_mouse_event;
+static void *qemu_put_mouse_event_opaque;
+
+void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque)
+{
+ qemu_put_kbd_event_opaque = opaque;
+ qemu_put_kbd_event = func;
+}
+
+void qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, void *opaque)
+{
+ qemu_put_mouse_event_opaque = opaque;
+ qemu_put_mouse_event = func;
+}
+
+void kbd_put_keycode(int keycode)
+{
+ if (qemu_put_kbd_event) {
+ qemu_put_kbd_event(qemu_put_kbd_event_opaque, keycode);
+ }
+}
+
+void kbd_mouse_event(int dx, int dy, int dz, int buttons_state)
+{
+ if (qemu_put_mouse_event) {
+ qemu_put_mouse_event(qemu_put_mouse_event_opaque,
+ dx, dy, dz, buttons_state);
+ }
+}
+
+/***********************************************************/
+/* timers */
+
+#if defined(__powerpc__)
+
+static inline uint32_t get_tbl(void)
+{
+ uint32_t tbl;
+ asm volatile("mftb %0" : "=r" (tbl));
+ return tbl;
+}
+
+static inline uint32_t get_tbu(void)
+{
+ uint32_t tbl;
+ asm volatile("mftbu %0" : "=r" (tbl));
+ return tbl;
+}
+
+int64_t cpu_get_real_ticks(void)
+{
+ uint32_t l, h, h1;
+ /* NOTE: we test if wrapping has occurred */
+ do {
+ h = get_tbu();
+ l = get_tbl();
+ h1 = get_tbu();
+ } while (h != h1);
+ return ((int64_t)h << 32) | l;
+}
+
+#elif defined(__i386__)
+
+int64_t cpu_get_real_ticks(void)
+{
+ int64_t val;
+ asm volatile ("rdtsc" : "=A" (val));
+ return val;
+}
+
+#elif defined(__x86_64__)
+
+int64_t cpu_get_real_ticks(void)
+{
+ uint32_t low,high;
+ int64_t val;
+ asm volatile("rdtsc" : "=a" (low), "=d" (high));
+ val = high;
+ val <<= 32;
+ val |= low;
+ return val;
+}
+
+#else
+#error unsupported CPU
+#endif
+
+static int64_t cpu_ticks_offset;
+static int cpu_ticks_enabled;
+int64_t cpu_virt_tsc;
+
+static inline int64_t cpu_get_ticks(void)
+{
+ if (!cpu_ticks_enabled) {
+ return cpu_ticks_offset;
+ } else {
+ return cpu_get_real_ticks() + cpu_ticks_offset;
+ }
+
+}
+
+/* enable cpu_get_ticks() */
+void cpu_enable_ticks(void)
+{
+ if (!cpu_ticks_enabled) {
+ cpu_ticks_offset -= cpu_get_real_ticks();
+ cpu_ticks_enabled = 1;
+ }
+}
+
+/* disable cpu_get_ticks() : the clock is stopped. You must not call
+ cpu_get_ticks() after that. */
+void cpu_disable_ticks(void)
+{
+ if (cpu_ticks_enabled) {
+ cpu_ticks_offset = cpu_get_ticks();
+ cpu_ticks_enabled = 0;
+ }
+}
+
+static int64_t get_clock(void)
+{
+#ifdef _WIN32
+ struct _timeb tb;
+ _ftime(&tb);
+ return ((int64_t)tb.time * 1000 + (int64_t)tb.millitm) * 1000;
+#else
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ return tv.tv_sec * 1000000LL + tv.tv_usec;
+#endif
+}
+
+void cpu_calibrate_ticks(void)
+{
+ int64_t usec, ticks;
+
+ usec = get_clock();
+ ticks = cpu_get_real_ticks();
+#ifdef _WIN32
+ Sleep(50);
+#else
+ usleep(50 * 1000);
+#endif
+ usec = get_clock() - usec;
+ ticks = cpu_get_real_ticks() - ticks;
+ ticks_per_sec = (ticks * 1000000LL + (usec >> 1)) / usec;
+}
+
+/* compute with 96 bit intermediate result: (a*b)/c */
+uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c)
+{
+ union {
+ uint64_t ll;
+ struct {
+#ifdef WORDS_BIGENDIAN
+ uint32_t high, low;
+#else
+ uint32_t low, high;
+#endif
+ } l;
+ } u, res;
+ uint64_t rl, rh;
+
+ u.ll = a;
+ rl = (uint64_t)u.l.low * (uint64_t)b;
+ rh = (uint64_t)u.l.high * (uint64_t)b;
+ rh += (rl >> 32);
+ res.l.high = rh / c;
+ res.l.low = (((rh % c) << 32) + (rl & 0xffffffff)) / c;
+ return res.ll;
+}
+
+#define QEMU_TIMER_REALTIME 0
+#define QEMU_TIMER_VIRTUAL 1
+
+struct QEMUClock {
+ int type;
+ /* XXX: add frequency */
+};
+
+struct QEMUTimer {
+ QEMUClock *clock;
+ int64_t expire_time;
+ QEMUTimerCB *cb;
+ void *opaque;
+ struct QEMUTimer *next;
+};
+
+QEMUClock *rt_clock;
+QEMUClock *vm_clock;
+
+static QEMUTimer *active_timers[2];
+#ifdef _WIN32
+static MMRESULT timerID;
+#else
+/* frequency of the times() clock tick */
+static int timer_freq;
+#endif
+
+QEMUClock *qemu_new_clock(int type)
+{
+ QEMUClock *clock;
+ clock = qemu_mallocz(sizeof(QEMUClock));
+ if (!clock)
+ return NULL;
+ clock->type = type;
+ return clock;
+}
+
+QEMUTimer *qemu_new_timer(QEMUClock *clock, QEMUTimerCB *cb, void *opaque)
+{
+ QEMUTimer *ts;
+
+ ts = qemu_mallocz(sizeof(QEMUTimer));
+ ts->clock = clock;
+ ts->cb = cb;
+ ts->opaque = opaque;
+ return ts;
+}
+
+void qemu_free_timer(QEMUTimer *ts)
+{
+ qemu_free(ts);
+}
+
+/* stop a timer, but do not dealloc it */
+void qemu_del_timer(QEMUTimer *ts)
+{
+ QEMUTimer **pt, *t;
+
+ /* NOTE: this code must be signal safe because
+ qemu_timer_expired() can be called from a signal. */
+ pt = &active_timers[ts->clock->type];
+ for(;;) {
+ t = *pt;
+ if (!t)
+ break;
+ if (t == ts) {
+ *pt = t->next;
+ break;
+ }
+ pt = &t->next;
+ }
+}
+
+/* modify the current timer so that it will be fired when current_time
+ >= expire_time. The corresponding callback will be called. */
+void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time)
+{
+ QEMUTimer **pt, *t;
+
+ qemu_del_timer(ts);
+
+ /* add the timer in the sorted list */
+ /* NOTE: this code must be signal safe because
+ qemu_timer_expired() can be called from a signal. */
+ pt = &active_timers[ts->clock->type];
+ for(;;) {
+ t = *pt;
+ if (!t)
+ break;
+ if (t->expire_time > expire_time)
+ break;
+ pt = &t->next;
+ }
+ ts->expire_time = expire_time;
+ ts->next = *pt;
+ *pt = ts;
+}
+
+int qemu_timer_pending(QEMUTimer *ts)
+{
+ QEMUTimer *t;
+ for(t = active_timers[ts->clock->type]; t != NULL; t = t->next) {
+ if (t == ts)
+ return 1;
+ }
+ return 0;
+}
+
+static inline int qemu_timer_expired(QEMUTimer *timer_head, int64_t current_time)
+{
+ if (!timer_head)
+ return 0;
+ return (timer_head->expire_time <= current_time);
+}
+
+static void qemu_run_timers(QEMUTimer **ptimer_head, int64_t current_time)
+{
+ QEMUTimer *ts;
+
+ for(;;) {
+ ts = *ptimer_head;
+ if (!ts || ts->expire_time > current_time)
+ break;
+ /* remove timer from the list before calling the callback */
+ *ptimer_head = ts->next;
+ ts->next = NULL;
+
+ /* run the callback (the timer list can be modified) */
+ ts->cb(ts->opaque);
+ }
+}
+
+int64_t qemu_get_clock(QEMUClock *clock)
+{
+ switch(clock->type) {
+ case QEMU_TIMER_REALTIME:
+#ifdef _WIN32
+ return GetTickCount();
+#else
+ {
+ struct tms tp;
+
+ /* Note that using gettimeofday() is not a good solution
+ for timers because its value change when the date is
+ modified. */
+ if (timer_freq == 100) {
+ return times(&tp) * 10;
+ } else {
+ return ((int64_t)times(&tp) * 1000) / timer_freq;
+ }
+ }
+#endif
+ default:
+ case QEMU_TIMER_VIRTUAL:
+ return cpu_get_ticks();
+ }
+}
+
+/* save a timer */
+void qemu_put_timer(QEMUFile *f, QEMUTimer *ts)
+{
+ uint64_t expire_time;
+
+ if (qemu_timer_pending(ts)) {
+ expire_time = ts->expire_time;
+ } else {
+ expire_time = -1;
+ }
+ qemu_put_be64(f, expire_time);
+}
+
+void qemu_get_timer(QEMUFile *f, QEMUTimer *ts)
+{
+ uint64_t expire_time;
+
+ expire_time = qemu_get_be64(f);
+ if (expire_time != -1) {
+ qemu_mod_timer(ts, expire_time);
+ } else {
+ qemu_del_timer(ts);
+ }
+}
+
+static void init_timers(void)
+{
+ rt_clock = qemu_new_clock(QEMU_TIMER_REALTIME);
+ vm_clock = qemu_new_clock(QEMU_TIMER_VIRTUAL);
+
+#ifdef _WIN32
+ {
+ int count=0;
+ timerID = timeSetEvent(10, // interval (ms)
+ 0, // resolution
+ host_alarm_handler, // function
+ (DWORD)&count, // user parameter
+ TIME_PERIODIC | TIME_CALLBACK_FUNCTION);
+ if( !timerID ) {
+ perror("failed timer alarm");
+ exit(1);
+ }
+ }
+ pit_min_timer_count = ((uint64_t)10000 * PIT_FREQ) / 1000000;
+#else
+ {
+ /* get times() syscall frequency */
+ timer_freq = sysconf(_SC_CLK_TCK);
+
+#ifndef TARGET_VMX
+ /* timer signal */
+ sigfillset(&act.sa_mask);
+ act.sa_flags = 0;
+#if defined (TARGET_I386) && defined(USE_CODE_COPY)
+ act.sa_flags |= SA_ONSTACK;
+#endif
+ act.sa_handler = host_alarm_handler;
+ sigaction(SIGALRM, &act, NULL);
+
+ itv.it_interval.tv_sec = 0;
+ itv.it_interval.tv_usec = 1000;
+ itv.it_value.tv_sec = 0;
+ itv.it_value.tv_usec = 10 * 1000;
+ setitimer(ITIMER_REAL, &itv, NULL);
+ /* we probe the tick duration of the kernel to inform the user if
+ the emulated kernel requested a too high timer frequency */
+ getitimer(ITIMER_REAL, &itv);
+
+#if defined(__linux__)
+ if (itv.it_interval.tv_usec > 1000) {
+ /* try to use /dev/rtc to have a faster timer */
+ if (start_rtc_timer() < 0)
+ goto use_itimer;
+ /* disable itimer */
+ itv.it_interval.tv_sec = 0;
+ itv.it_interval.tv_usec = 0;
+ itv.it_value.tv_sec = 0;
+ itv.it_value.tv_usec = 0;
+ setitimer(ITIMER_REAL, &itv, NULL);
+
+ /* use the RTC */
+ sigaction(SIGIO, &act, NULL);
+ fcntl(rtc_fd, F_SETFL, O_ASYNC);
+ fcntl(rtc_fd, F_SETOWN, getpid());
+ } else
+#endif /* defined(__linux__) */
+ {
+ use_itimer:
+ pit_min_timer_count = ((uint64_t)itv.it_interval.tv_usec *
+ PIT_FREQ) / 1000000;
+ }
+#endif /* TARGET_VMX */
+ }
+#endif
+}
+
+void quit_timers(void)
+{
+#ifdef _WIN32
+ timeKillEvent(timerID);
+#endif
+}
+
+/***********************************************************/
+/* character device */
+
+int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len)
+{
+ return s->chr_write(s, buf, len);
+}
+
+void qemu_chr_printf(CharDriverState *s, const char *fmt, ...)
+{
+ char buf[4096];
+ va_list ap;
+ va_start(ap, fmt);
+ vsnprintf(buf, sizeof(buf), fmt, ap);
+ qemu_chr_write(s, buf, strlen(buf));
+ va_end(ap);
+}
+
+void qemu_chr_send_event(CharDriverState *s, int event)
+{
+ if (s->chr_send_event)
+ s->chr_send_event(s, event);
+}
+
+void qemu_chr_add_read_handler(CharDriverState *s,
+ IOCanRWHandler *fd_can_read,
+ IOReadHandler *fd_read, void *opaque)
+{
+ s->chr_add_read_handler(s, fd_can_read, fd_read, opaque);
+}
+
+void qemu_chr_add_event_handler(CharDriverState *s, IOEventHandler *chr_event)
+{
+ s->chr_event = chr_event;
+}
+
+static int null_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+{
+ return len;
+}
+
+static void null_chr_add_read_handler(CharDriverState *chr,
+ IOCanRWHandler *fd_can_read,
+ IOReadHandler *fd_read, void *opaque)
+{
+}
+
+CharDriverState *qemu_chr_open_null(void)
+{
+ CharDriverState *chr;
+
+ chr = qemu_mallocz(sizeof(CharDriverState));
+ if (!chr)
+ return NULL;
+ chr->chr_write = null_chr_write;
+ chr->chr_add_read_handler = null_chr_add_read_handler;
+ return chr;
+}
+
+#ifndef _WIN32
+
+typedef struct {
+ int fd_in, fd_out;
+ /* for nographic stdio only */
+ IOCanRWHandler *fd_can_read;
+ IOReadHandler *fd_read;
+ void *fd_opaque;
+} FDCharDriver;
+
+#define STDIO_MAX_CLIENTS 2
+
+static int stdio_nb_clients;
+static CharDriverState *stdio_clients[STDIO_MAX_CLIENTS];
+
+static int unix_write(int fd, const uint8_t *buf, int len1)
+{
+ int ret, len;
+
+ len = len1;
+ while (len > 0) {
+ ret = write(fd, buf, len);
+ if (ret < 0) {
+ if (errno != EINTR && errno != EAGAIN)
+ return -1;
+ } else if (ret == 0) {
+ break;
+ } else {
+ buf += ret;
+ len -= ret;
+ }
+ }
+ return len1 - len;
+}
+
+static int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len)
+{
+ FDCharDriver *s = chr->opaque;
+ return unix_write(s->fd_out, buf, len);
+}
+
+static void fd_chr_add_read_handler(CharDriverState *chr,
+ IOCanRWHandler *fd_can_read,
+ IOReadHandler *fd_read, void *opaque)
+{
+ FDCharDriver *s = chr->opaque;
+
+ if (nographic && s->fd_in == 0) {
+ s->fd_can_read = fd_can_read;
+ s->fd_read = fd_read;
+ s->fd_opaque = opaque;
+ } else {
+ qemu_add_fd_read_handler(s->fd_in, fd_can_read, fd_read, opaque);
+ }
+}
+
+/* open a character device to a unix fd */
+CharDriverState *qemu_chr_open_fd(int fd_in, int fd_out)
+{
+ CharDriverState *chr;
+ FDCharDriver *s;
+
+ chr = qemu_mallocz(sizeof(CharDriverState));
+ if (!chr)
+ return NULL;
+ s = qemu_mallocz(sizeof(FDCharDriver));
+ if (!s) {
+ free(chr);
+ return NULL;
+ }
+ s->fd_in = fd_in;
+ s->fd_out = fd_out;
+ chr->opaque = s;
+ chr->chr_write = fd_chr_write;
+ chr->chr_add_read_handler = fd_chr_add_read_handler;
+ return chr;
+}
+
+/* for STDIO, we handle the case where several clients use it
+ (nographic mode) */
+
+#define TERM_ESCAPE 0x01 /* ctrl-a is used for escape */
+
+static int term_got_escape, client_index;
+
+void term_print_help(void)
+{
+ printf("\n"
+ "C-a h print this help\n"
+ "C-a x exit emulator\n"
+ "C-a s save disk data back to file (if -snapshot)\n"
+ "C-a b send break (magic sysrq)\n"
+ "C-a c switch between console and monitor\n"
+ "C-a C-a send C-a\n"
+ );
+}
+
+/* called when a char is received */
+static void stdio_received_byte(int ch)
+{
+ if (term_got_escape) {
+ term_got_escape = 0;
+ switch(ch) {
+ case 'h':
+ term_print_help();
+ break;
+ case 'x':
+ exit(0);
+ break;
+ case 's':
+ {
+ int i;
+ for (i = 0; i < MAX_DISKS; i++) {
+ if (bs_table[i])
+ bdrv_commit(bs_table[i]);
+ }
+ }
+ break;
+ case 'b':
+ if (client_index < stdio_nb_clients) {
+ CharDriverState *chr;
+ FDCharDriver *s;
+
+ chr = stdio_clients[client_index];
+ s = chr->opaque;
+ chr->chr_event(s->fd_opaque, CHR_EVENT_BREAK);
+ }
+ break;
+ case 'c':
+ client_index++;
+ if (client_index >= stdio_nb_clients)
+ client_index = 0;
+ if (client_index == 0) {
+ /* send a new line in the monitor to get the prompt */
+ ch = '\r';
+ goto send_char;
+ }
+ break;
+ case TERM_ESCAPE:
+ goto send_char;
+ }
+ } else if (ch == TERM_ESCAPE) {
+ term_got_escape = 1;
+ } else {
+ send_char:
+ if (client_index < stdio_nb_clients) {
+ uint8_t buf[1];
+ CharDriverState *chr;
+ FDCharDriver *s;
+
+ chr = stdio_clients[client_index];
+ s = chr->opaque;
+ buf[0] = ch;
+ /* XXX: should queue the char if the device is not
+ ready */
+ if (s->fd_can_read(s->fd_opaque) > 0)
+ s->fd_read(s->fd_opaque, buf, 1);
+ }
+ }
+}
+
+static int stdio_can_read(void *opaque)
+{
+ /* XXX: not strictly correct */
+ return 1;
+}
+
+static void stdio_read(void *opaque, const uint8_t *buf, int size)
+{
+ int i;
+ for(i = 0; i < size; i++)
+ stdio_received_byte(buf[i]);
+}
+
+/* init terminal so that we can grab keys */
+static struct termios oldtty;
+static int old_fd0_flags;
+
+static void term_exit(void)
+{
+ tcsetattr (0, TCSANOW, &oldtty);
+ fcntl(0, F_SETFL, old_fd0_flags);
+}
+
+static void term_init(void)
+{
+ struct termios tty;
+
+ tcgetattr (0, &tty);
+ oldtty = tty;
+ old_fd0_flags = fcntl(0, F_GETFL);
+
+ tty.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
+ |INLCR|IGNCR|ICRNL|IXON);
+ tty.c_oflag |= OPOST;
+ tty.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN);
+ /* if graphical mode, we allow Ctrl-C handling */
+ if (nographic)
+ tty.c_lflag &= ~ISIG;
+ tty.c_cflag &= ~(CSIZE|PARENB);
+ tty.c_cflag |= CS8;
+ tty.c_cc[VMIN] = 1;
+ tty.c_cc[VTIME] = 0;
+
+ tcsetattr (0, TCSANOW, &tty);
+
+ atexit(term_exit);
+
+ fcntl(0, F_SETFL, O_NONBLOCK);
+}
+
+CharDriverState *qemu_chr_open_stdio(void)
+{
+ CharDriverState *chr;
+
+ if (nographic) {
+ if (stdio_nb_clients >= STDIO_MAX_CLIENTS)
+ return NULL;
+ chr = qemu_chr_open_fd(0, 1);
+ if (stdio_nb_clients == 0)
+ qemu_add_fd_read_handler(0, stdio_can_read, stdio_read, NULL);
+ client_index = stdio_nb_clients;
+ } else {
+ if (stdio_nb_clients != 0)
+ return NULL;
+ chr = qemu_chr_open_fd(0, 1);
+ }
+ stdio_clients[stdio_nb_clients++] = chr;
+ if (stdio_nb_clients == 1) {
+ /* set the terminal in raw mode */
+ term_init();
+ }
+ return chr;
+}
+
+#if defined(__linux__)
+CharDriverState *qemu_chr_open_pty(void)
+{
+ char slave_name[1024];
+ int master_fd, slave_fd;
+
+ /* Not satisfying */
+ if (openpty(&master_fd, &slave_fd, slave_name, NULL, NULL) < 0) {
+ return NULL;
+ }
+ fprintf(stderr, "char device redirected to %s\n", slave_name);
+ return qemu_chr_open_fd(master_fd, master_fd);
+}
+#else
+CharDriverState *qemu_chr_open_pty(void)
+{
+ return NULL;
+}
+#endif
+
+#endif /* !defined(_WIN32) */
+
+CharDriverState *qemu_chr_open(const char *filename)
+{
+ if (!strcmp(filename, "vc")) {
+ return text_console_init(&display_state);
+ } else if (!strcmp(filename, "null")) {
+ return qemu_chr_open_null();
+ } else
+#ifndef _WIN32
+ if (!strcmp(filename, "pty")) {
+ return qemu_chr_open_pty();
+ } else if (!strcmp(filename, "stdio")) {
+ return qemu_chr_open_stdio();
+ } else
+#endif
+ {
+ return NULL;
+ }
+}
+
+/***********************************************************/
+/* Linux network device redirectors */
+
+void hex_dump(FILE *f, const uint8_t *buf, int size)
+{
+ int len, i, j, c;
+
+ for(i=0;i<size;i+=16) {
+ len = size - i;
+ if (len > 16)
+ len = 16;
+ fprintf(f, "%08x ", i);
+ for(j=0;j<16;j++) {
+ if (j < len)
+ fprintf(f, " %02x", buf[i+j]);
+ else
+ fprintf(f, " ");
+ }
+ fprintf(f, " ");
+ for(j=0;j<len;j++) {
+ c = buf[i+j];
+ if (c < ' ' || c > '~')
+ c = '.';
+ fprintf(f, "%c", c);
+ }
+ fprintf(f, "\n");
+ }
+}
+
+void qemu_send_packet(NetDriverState *nd, const uint8_t *buf, int size)
+{
+ nd->send_packet(nd, buf, size);
+}
+
+void qemu_add_read_packet(NetDriverState *nd, IOCanRWHandler *fd_can_read,
+ IOReadHandler *fd_read, void *opaque)
+{
+ nd->add_read_packet(nd, fd_can_read, fd_read, opaque);
+}
+
+/* dummy network adapter */
+
+static void dummy_send_packet(NetDriverState *nd, const uint8_t *buf, int size)
+{
+}
+
+static void dummy_add_read_packet(NetDriverState *nd,
+ IOCanRWHandler *fd_can_read,
+ IOReadHandler *fd_read, void *opaque)
+{
+}
+
+static int net_dummy_init(NetDriverState *nd)
+{
+ nd->send_packet = dummy_send_packet;
+ nd->add_read_packet = dummy_add_read_packet;
+ pstrcpy(nd->ifname, sizeof(nd->ifname), "dummy");
+ return 0;
+}
+
+#if defined(CONFIG_SLIRP)
+
+/* slirp network adapter */
+
+static void *slirp_fd_opaque;
+static IOCanRWHandler *slirp_fd_can_read;
+static IOReadHandler *slirp_fd_read;
+static int slirp_inited;
+
+int slirp_can_output(void)
+{
+ return slirp_fd_can_read(slirp_fd_opaque);
+}
+
+void slirp_output(const uint8_t *pkt, int pkt_len)
+{
+#if 0
+ printf("output:\n");
+ hex_dump(stdout, pkt, pkt_len);
+#endif
+ slirp_fd_read(slirp_fd_opaque, pkt, pkt_len);
+}
+
+static void slirp_send_packet(NetDriverState *nd, const uint8_t *buf, int size)
+{
+#if 0
+ printf("input:\n");
+ hex_dump(stdout, buf, size);
+#endif
+ slirp_input(buf, size);
+}
+
+static void slirp_add_read_packet(NetDriverState *nd,
+ IOCanRWHandler *fd_can_read,
+ IOReadHandler *fd_read, void *opaque)
+{
+ slirp_fd_opaque = opaque;
+ slirp_fd_can_read = fd_can_read;
+ slirp_fd_read = fd_read;
+}
+
+static int net_slirp_init(NetDriverState *nd)
+{
+ if (!slirp_inited) {
+ slirp_inited = 1;
+ slirp_init();
+ }
+ nd->send_packet = slirp_send_packet;
+ nd->add_read_packet = slirp_add_read_packet;
+ pstrcpy(nd->ifname, sizeof(nd->ifname), "slirp");
+ return 0;
+}
+
+static int get_str_sep(char *buf, int buf_size, const char **pp, int sep)
+{
+ const char *p, *p1;
+ int len;
+ p = *pp;
+ p1 = strchr(p, sep);
+ if (!p1)
+ return -1;
+ len = p1 - p;
+ p1++;
+ if (buf_size > 0) {
+ if (len > buf_size - 1)
+ len = buf_size - 1;
+ memcpy(buf, p, len);
+ buf[len] = '\0';
+ }
+ *pp = p1;
+ return 0;
+}
+
+static void net_slirp_redir(const char *redir_str)
+{
+ int is_udp;
+ char buf[256], *r;
+ const char *p;
+ struct in_addr guest_addr;
+ int host_port, guest_port;
+
+ if (!slirp_inited) {
+ slirp_inited = 1;
+ slirp_init();
+ }
+
+ p = redir_str;
+ if (get_str_sep(buf, sizeof(buf), &p, ':') < 0)
+ goto fail;
+ if (!strcmp(buf, "tcp")) {
+ is_udp = 0;
+ } else if (!strcmp(buf, "udp")) {
+ is_udp = 1;
+ } else {
+ goto fail;
+ }
+
+ if (get_str_sep(buf, sizeof(buf), &p, ':') < 0)
+ goto fail;
+ host_port = strtol(buf, &r, 0);
+ if (r == buf)
+ goto fail;
+
+ if (get_str_sep(buf, sizeof(buf), &p, ':') < 0)
+ goto fail;
+ if (buf[0] == '\0') {
+ pstrcpy(buf, sizeof(buf), "10.0.2.15");
+ }
+ if (!inet_aton(buf, &guest_addr))
+ goto fail;
+
+ guest_port = strtol(p, &r, 0);
+ if (r == p)
+ goto fail;
+
+ if (slirp_redir(is_udp, host_port, guest_addr, guest_port) < 0) {
+ fprintf(stderr, "qemu: could not set up redirection\n");
+ exit(1);
+ }
+ return;
+ fail:
+ fprintf(stderr, "qemu: syntax: -redir [tcp|udp]:host-port:[guest-host]:guest-port\n");
+ exit(1);
+}
+
+#ifndef _WIN32
+
+char smb_dir[1024];
+
+static void smb_exit(void)
+{
+ DIR *d;
+ struct dirent *de;
+ char filename[1024];
+
+ /* erase all the files in the directory */
+ d = opendir(smb_dir);
+ for(;;) {
+ de = readdir(d);
+ if (!de)
+ break;
+ if (strcmp(de->d_name, ".") != 0 &&
+ strcmp(de->d_name, "..") != 0) {
+ snprintf(filename, sizeof(filename), "%s/%s",
+ smb_dir, de->d_name);
+ unlink(filename);
+ }
+ }
+ closedir(d);
+ rmdir(smb_dir);
+}
+
+/* automatic user mode samba server configuration */
+void net_slirp_smb(const char *exported_dir)
+{
+ char smb_conf[1024];
+ char smb_cmdline[1024];
+ FILE *f;
+
+ if (!slirp_inited) {
+ slirp_inited = 1;
+ slirp_init();
+ }
+
+ /* XXX: better tmp dir construction */
+ snprintf(smb_dir, sizeof(smb_dir), "/tmp/qemu-smb.%d", getpid());
+ if (mkdir(smb_dir, 0700) < 0) {
+ fprintf(stderr, "qemu: could not create samba server dir '%s'\n", smb_dir);
+ exit(1);
+ }
+ snprintf(smb_conf, sizeof(smb_conf), "%s/%s", smb_dir, "smb.conf");
+
+ f = fopen(smb_conf, "w");
+ if (!f) {
+ fprintf(stderr, "qemu: could not create samba server configuration file '%s'\n", smb_conf);
+ exit(1);
+ }
+ fprintf(f,
+ "[global]\n"
+ "pid directory=%s\n"
+ "lock directory=%s\n"
+ "log file=%s/log.smbd\n"
+ "smb passwd file=%s/smbpasswd\n"
+ "security = share\n"
+ "[qemu]\n"
+ "path=%s\n"
+ "read only=no\n"
+ "guest ok=yes\n",
+ smb_dir,
+ smb_dir,
+ smb_dir,
+ smb_dir,
+ exported_dir
+ );
+ fclose(f);
+ atexit(smb_exit);
+
+ snprintf(smb_cmdline, sizeof(smb_cmdline), "/usr/sbin/smbd -s %s",
+ smb_conf);
+
+ slirp_add_exec(0, smb_cmdline, 4, 139);
+}
+
+#endif /* !defined(_WIN32) */
+
+#endif /* CONFIG_SLIRP */
+
+#if !defined(_WIN32)
+#ifdef _BSD
+static int tun_open(char *ifname, int ifname_size)
+{
+ int fd;
+ char *dev;
+ struct stat s;
+
+ fd = open("/dev/tap", O_RDWR);
+ if (fd < 0) {
+ fprintf(stderr, "warning: could not open /dev/tap: no virtual network emulation\n");
+ return -1;
+ }
+
+ fstat(fd, &s);
+ dev = devname(s.st_rdev, S_IFCHR);
+ pstrcpy(ifname, ifname_size, dev);
+
+ fcntl(fd, F_SETFL, O_NONBLOCK);
+ return fd;
+}
+#else
+static int tun_open(char *ifname, int ifname_size)
+{
+ struct ifreq ifr;
+ int fd, ret;
+
+ fd = open("/dev/net/tun", O_RDWR);
+ if (fd < 0) {
+ fprintf(stderr, "warning: could not open /dev/net/tun: no virtual network emulation\n");
+ return -1;
+ }
+ memset(&ifr, 0, sizeof(ifr));
+ ifr.ifr_flags = IFF_TAP | IFF_NO_PI;
+ pstrcpy(ifr.ifr_name, IFNAMSIZ, "tun%d");
+ ret = ioctl(fd, TUNSETIFF, (void *) &ifr);
+ if (ret != 0) {
+ fprintf(stderr, "warning: could not configure /dev/net/tun: no virtual network emulation\n");
+ close(fd);
+ return -1;
+ }
+ printf("Connected to host network interface: %s\n", ifr.ifr_name);
+ pstrcpy(ifname, ifname_size, ifr.ifr_name);
+ fcntl(fd, F_SETFL, O_NONBLOCK);
+ return fd;
+}
+#endif
+
+static void tun_send_packet(NetDriverState *nd, const uint8_t *buf, int size)
+{
+ write(nd->fd, buf, size);
+}
+
+static void tun_add_read_packet(NetDriverState *nd,
+ IOCanRWHandler *fd_can_read,
+ IOReadHandler *fd_read, void *opaque)
+{
+ qemu_add_fd_read_handler(nd->fd, fd_can_read, fd_read, opaque);
+}
+
+static int net_tun_init(NetDriverState *nd)
+{
+ int pid, status;
+ char *args[3];
+ char **parg;
+
+ nd->fd = tun_open(nd->ifname, sizeof(nd->ifname));
+ if (nd->fd < 0)
+ return -1;
+
+ /* try to launch network init script */
+ pid = fork();
+ if (pid >= 0) {
+ if (pid == 0) {
+ parg = args;
+ *parg++ = network_script;
+ *parg++ = nd->ifname;
+ *parg++ = NULL;
+ execv(network_script, args);
+ exit(1);
+ }
+ while (waitpid(pid, &status, 0) != pid);
+ if (!WIFEXITED(status) ||
+ WEXITSTATUS(status) != 0) {
+ fprintf(stderr, "%s: could not launch network script\n",
+ network_script);
+ }
+ }
+ nd->send_packet = tun_send_packet;
+ nd->add_read_packet = tun_add_read_packet;
+ return 0;
+}
+
+static int net_fd_init(NetDriverState *nd, int fd)
+{
+ nd->fd = fd;
+ nd->send_packet = tun_send_packet;
+ nd->add_read_packet = tun_add_read_packet;
+ pstrcpy(nd->ifname, sizeof(nd->ifname), "tunfd");
+ return 0;
+}
+
+#endif /* !_WIN32 */
+
+/***********************************************************/
+/* dumb display */
+
+static void dumb_update(DisplayState *ds, int x, int y, int w, int h)
+{
+}
+
+static void dumb_resize(DisplayState *ds, int w, int h)
+{
+}
+
+static void dumb_refresh(DisplayState *ds)
+{
+ vga_update_display();
+}
+
+void dumb_display_init(DisplayState *ds)
+{
+ ds->data = NULL;
+ ds->linesize = 0;
+ ds->depth = 0;
+ ds->dpy_update = dumb_update;
+ ds->dpy_resize = dumb_resize;
+ ds->dpy_refresh = dumb_refresh;
+}
+
+#if !defined(CONFIG_SOFTMMU)
+/***********************************************************/
+/* cpu signal handler */
+static void host_segv_handler(int host_signum, siginfo_t *info,
+ void *puc)
+{
+ abort();
+}
+#endif
+
+/***********************************************************/
+/* I/O handling */
+
+#define MAX_IO_HANDLERS 64
+
+typedef struct IOHandlerRecord {
+ int fd;
+ IOCanRWHandler *fd_can_read;
+ IOReadHandler *fd_read;
+ void *opaque;
+ /* temporary data */
+ struct pollfd *ufd;
+ int max_size;
+ struct IOHandlerRecord *next;
+} IOHandlerRecord;
+
+static IOHandlerRecord *first_io_handler;
+
+int qemu_add_fd_read_handler(int fd, IOCanRWHandler *fd_can_read,
+ IOReadHandler *fd_read, void *opaque)
+{
+ IOHandlerRecord *ioh;
+
+ ioh = qemu_mallocz(sizeof(IOHandlerRecord));
+ if (!ioh)
+ return -1;
+ ioh->fd = fd;
+ ioh->fd_can_read = fd_can_read;
+ ioh->fd_read = fd_read;
+ ioh->opaque = opaque;
+ ioh->next = first_io_handler;
+ first_io_handler = ioh;
+ return 0;
+}
+
+void qemu_del_fd_read_handler(int fd)
+{
+ IOHandlerRecord **pioh, *ioh;
+
+ pioh = &first_io_handler;
+ for(;;) {
+ ioh = *pioh;
+ if (ioh == NULL)
+ break;
+ if (ioh->fd == fd) {
+ *pioh = ioh->next;
+ break;
+ }
+ pioh = &ioh->next;
+ }
+}
+
+/***********************************************************/
+/* savevm/loadvm support */
+
+void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size)
+{
+ fwrite(buf, 1, size, f);
+}
+
+void qemu_put_byte(QEMUFile *f, int v)
+{
+ fputc(v, f);
+}
+
+void qemu_put_be16(QEMUFile *f, unsigned int v)
+{
+ qemu_put_byte(f, v >> 8);
+ qemu_put_byte(f, v);
+}
+
+void qemu_put_be32(QEMUFile *f, unsigned int v)
+{
+ qemu_put_byte(f, v >> 24);
+ qemu_put_byte(f, v >> 16);
+ qemu_put_byte(f, v >> 8);
+ qemu_put_byte(f, v);
+}
+
+void qemu_put_be64(QEMUFile *f, uint64_t v)
+{
+ qemu_put_be32(f, v >> 32);
+ qemu_put_be32(f, v);
+}
+
+int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size)
+{
+ return fread(buf, 1, size, f);
+}
+
+int qemu_get_byte(QEMUFile *f)
+{
+ int v;
+ v = fgetc(f);
+ if (v == EOF)
+ return 0;
+ else
+ return v;
+}
+
+unsigned int qemu_get_be16(QEMUFile *f)
+{
+ unsigned int v;
+ v = qemu_get_byte(f) << 8;
+ v |= qemu_get_byte(f);
+ return v;
+}
+
+unsigned int qemu_get_be32(QEMUFile *f)
+{
+ unsigned int v;
+ v = qemu_get_byte(f) << 24;
+ v |= qemu_get_byte(f) << 16;
+ v |= qemu_get_byte(f) << 8;
+ v |= qemu_get_byte(f);
+ return v;
+}
+
+uint64_t qemu_get_be64(QEMUFile *f)
+{
+ uint64_t v;
+ v = (uint64_t)qemu_get_be32(f) << 32;
+ v |= qemu_get_be32(f);
+ return v;
+}
+
+int64_t qemu_ftell(QEMUFile *f)
+{
+ return ftell(f);
+}
+
+int64_t qemu_fseek(QEMUFile *f, int64_t pos, int whence)
+{
+ if (fseek(f, pos, whence) < 0)
+ return -1;
+ return ftell(f);
+}
+
+typedef struct SaveStateEntry {
+ char idstr[256];
+ int instance_id;
+ int version_id;
+ SaveStateHandler *save_state;
+ LoadStateHandler *load_state;
+ void *opaque;
+ struct SaveStateEntry *next;
+} SaveStateEntry;
+
+static SaveStateEntry *first_se;
+
+int register_savevm(const char *idstr,
+ int instance_id,
+ int version_id,
+ SaveStateHandler *save_state,
+ LoadStateHandler *load_state,
+ void *opaque)
+{
+ SaveStateEntry *se, **pse;
+
+ se = qemu_malloc(sizeof(SaveStateEntry));
+ if (!se)
+ return -1;
+ pstrcpy(se->idstr, sizeof(se->idstr), idstr);
+ se->instance_id = instance_id;
+ se->version_id = version_id;
+ se->save_state = save_state;
+ se->load_state = load_state;
+ se->opaque = opaque;
+ se->next = NULL;
+
+ /* add at the end of list */
+ pse = &first_se;
+ while (*pse != NULL)
+ pse = &(*pse)->next;
+ *pse = se;
+ return 0;
+}
+
+#define QEMU_VM_FILE_MAGIC 0x5145564d
+#define QEMU_VM_FILE_VERSION 0x00000001
+
+int qemu_savevm(const char *filename)
+{
+ SaveStateEntry *se;
+ QEMUFile *f;
+ int len, len_pos, cur_pos, saved_vm_running, ret;
+
+ saved_vm_running = vm_running;
+ vm_stop(0);
+
+ f = fopen(filename, "wb");
+ if (!f) {
+ ret = -1;
+ goto the_end;
+ }
+
+ qemu_put_be32(f, QEMU_VM_FILE_MAGIC);
+ qemu_put_be32(f, QEMU_VM_FILE_VERSION);
+
+ for(se = first_se; se != NULL; se = se->next) {
+ /* ID string */
+ len = strlen(se->idstr);
+ qemu_put_byte(f, len);
+ qemu_put_buffer(f, se->idstr, len);
+
+ qemu_put_be32(f, se->instance_id);
+ qemu_put_be32(f, se->version_id);
+
+ /* record size: filled later */
+ len_pos = ftell(f);
+ qemu_put_be32(f, 0);
+
+ se->save_state(f, se->opaque);
+
+ /* fill record size */
+ cur_pos = ftell(f);
+ len = ftell(f) - len_pos - 4;
+ fseek(f, len_pos, SEEK_SET);
+ qemu_put_be32(f, len);
+ fseek(f, cur_pos, SEEK_SET);
+ }
+
+ fclose(f);
+ ret = 0;
+ the_end:
+ if (saved_vm_running)
+ vm_start();
+ return ret;
+}
+
+static SaveStateEntry *find_se(const char *idstr, int instance_id)
+{
+ SaveStateEntry *se;
+
+ for(se = first_se; se != NULL; se = se->next) {
+ if (!strcmp(se->idstr, idstr) &&
+ instance_id == se->instance_id)
+ return se;
+ }
+ return NULL;
+}
+
+int qemu_loadvm(const char *filename)
+{
+ SaveStateEntry *se;
+ QEMUFile *f;
+ int len, cur_pos, ret, instance_id, record_len, version_id;
+ int saved_vm_running;
+ unsigned int v;
+ char idstr[256];
+
+ saved_vm_running = vm_running;
+ vm_stop(0);
+
+ f = fopen(filename, "rb");
+ if (!f) {
+ ret = -1;
+ goto the_end;
+ }
+
+ v = qemu_get_be32(f);
+ if (v != QEMU_VM_FILE_MAGIC)
+ goto fail;
+ v = qemu_get_be32(f);
+ if (v != QEMU_VM_FILE_VERSION) {
+ fail:
+ fclose(f);
+ ret = -1;
+ goto the_end;
+ }
+ for(;;) {
+#if defined (DO_TB_FLUSH)
+ tb_flush(global_env);
+#endif
+ len = qemu_get_byte(f);
+ if (feof(f))
+ break;
+ qemu_get_buffer(f, idstr, len);
+ idstr[len] = '\0';
+ instance_id = qemu_get_be32(f);
+ version_id = qemu_get_be32(f);
+ record_len = qemu_get_be32(f);
+#if 0
+ printf("idstr=%s instance=0x%x version=%d len=%d\n",
+ idstr, instance_id, version_id, record_len);
+#endif
+ cur_pos = ftell(f);
+ se = find_se(idstr, instance_id);
+ if (!se) {
+ fprintf(stderr, "qemu: warning: instance 0x%x of device '%s' not present in current VM\n",
+ instance_id, idstr);
+ } else {
+ ret = se->load_state(f, se->opaque, version_id);
+ if (ret < 0) {
+ fprintf(stderr, "qemu: warning: error while loading state for instance 0x%x of device '%s'\n",
+ instance_id, idstr);
+ }
+ }
+ /* always seek to exact end of record */
+ qemu_fseek(f, cur_pos + record_len, SEEK_SET);
+ }
+ fclose(f);
+ ret = 0;
+ the_end:
+ if (saved_vm_running)
+ vm_start();
+ return ret;
+}
+
+/***********************************************************/
+/* main execution loop */
+
+void gui_update(void *opaque)
+{
+ display_state.dpy_refresh(&display_state);
+ qemu_mod_timer(gui_timer, GUI_REFRESH_INTERVAL + qemu_get_clock(rt_clock));
+}
+void polling_handler(void *opaque)
+{
+#ifndef _WIN32
+ struct pollfd ufds[MAX_IO_HANDLERS + 1], *pf;
+ IOHandlerRecord *ioh, *ioh_next;
+ uint8_t buf[4096];
+ int n, max_size;
+#endif
+ int timeout = 0;
+ int ret;
+
+#ifdef _WIN32
+ if (timeout > 0)
+ Sleep(timeout);
+#else
+ /* poll any events */
+ /* XXX: separate device handlers from system ones */
+ pf = ufds;
+ for(ioh = first_io_handler; ioh != NULL; ioh = ioh->next) {
+ if (!ioh->fd_can_read) {
+ max_size = 0;
+ pf->fd = ioh->fd;
+ pf->events = POLLIN;
+ ioh->ufd = pf;
+ pf++;
+ } else {
+ max_size = ioh->fd_can_read(ioh->opaque);
+ if (max_size > 0) {
+ if (max_size > sizeof(buf))
+ max_size = sizeof(buf);
+ pf->fd = ioh->fd;
+ pf->events = POLLIN;
+ ioh->ufd = pf;
+ pf++;
+ } else {
+ ioh->ufd = NULL;
+ }
+ }
+ ioh->max_size = max_size;
+ }
+
+ ret = poll(ufds, pf - ufds, timeout);
+ if (ret > 0) {
+ /* XXX: better handling of removal */
+ for(ioh = first_io_handler; ioh != NULL; ioh = ioh_next) {
+ ioh_next = ioh->next;
+ pf = ioh->ufd;
+ if (pf) {
+ if (pf->revents & POLLIN) {
+ if (ioh->max_size == 0) {
+ /* just a read event */
+ ioh->fd_read(ioh->opaque, NULL, 0);
+ } else {
+ n = read(ioh->fd, buf, ioh->max_size);
+ if (n >= 0) {
+ ioh->fd_read(ioh->opaque, buf, n);
+ } else if (errno != EAGAIN) {
+ ioh->fd_read(ioh->opaque, NULL, -errno);
+ }
+ }
+ }
+ }
+ }
+ }
+#endif /* !defined(_WIN32) */
+
+ qemu_mod_timer(polling_timer, POLLING_INTERVAL + qemu_get_clock(rt_clock));
+}
+
+
+/* XXX: support several handlers */
+VMStopHandler *vm_stop_cb;
+VMStopHandler *vm_stop_opaque;
+
+int qemu_add_vm_stop_handler(VMStopHandler *cb, void *opaque)
+{
+ vm_stop_cb = cb;
+ vm_stop_opaque = opaque;
+ return 0;
+}
+
+void qemu_del_vm_stop_handler(VMStopHandler *cb, void *opaque)
+{
+ vm_stop_cb = NULL;
+}
+
+void vm_start(void)
+{
+ if (!vm_running) {
+ cpu_enable_ticks();
+ vm_running = 1;
+ }
+}
+
+void vm_stop(int reason)
+{
+ if (vm_running) {
+ cpu_disable_ticks();
+ vm_running = 0;
+ if (reason != 0) {
+ if (vm_stop_cb) {
+ vm_stop_cb(vm_stop_opaque, reason);
+ }
+ }
+ }
+}
+
+/* reset/shutdown handler */
+
+typedef struct QEMUResetEntry {
+ QEMUResetHandler *func;
+ void *opaque;
+ struct QEMUResetEntry *next;
+} QEMUResetEntry;
+
+static QEMUResetEntry *first_reset_entry;
+static int reset_requested;
+int shutdown_requested;
+
+void qemu_register_reset(QEMUResetHandler *func, void *opaque)
+{
+ QEMUResetEntry **pre, *re;
+
+ pre = &first_reset_entry;
+ while (*pre != NULL)
+ pre = &(*pre)->next;
+ re = qemu_mallocz(sizeof(QEMUResetEntry));
+ re->func = func;
+ re->opaque = opaque;
+ re->next = NULL;
+ *pre = re;
+}
+
+void qemu_system_reset(void)
+{
+ QEMUResetEntry *re;
+
+ /* reset all devices */
+ for(re = first_reset_entry; re != NULL; re = re->next) {
+ re->func(re->opaque);
+ }
+}
+
+void qemu_system_reset_request(void)
+{
+ reset_requested = 1;
+ cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT);
+}
+
+void qemu_system_shutdown_request(void)
+{
+ shutdown_requested = 1;
+ cpu_interrupt(cpu_single_env, CPU_INTERRUPT_EXIT);
+}
+
+void main_loop_wait(int timeout)
+{
+ if (vm_running) {
+ qemu_run_timers(&active_timers[QEMU_TIMER_VIRTUAL],
+ qemu_get_clock(vm_clock));
+ /* run dma transfers, if any */
+ DMA_run();
+ }
+
+ /* real time timers */
+ qemu_run_timers(&active_timers[QEMU_TIMER_REALTIME],
+ qemu_get_clock(rt_clock));
+}
+
+void help(void)
+{
+ printf("QEMU PC emulator version " QEMU_VERSION ", Copyright (c) 2003-2004 Fabrice Bellard\n"
+ "usage: %s [options] [disk_image]\n"
+ "\n"
+ "'disk_image' is a raw hard image image for IDE hard disk 0\n"
+ "\n"
+ "Standard options:\n"
+ "-fda/-fdb file use 'file' as floppy disk 0/1 image\n"
+ "-hda/-hdb file use 'file' as IDE hard disk 0/1 image\n"
+ "-hdc/-hdd file use 'file' as IDE hard disk 2/3 image\n"
+ "-cdrom file use 'file' as IDE cdrom image (cdrom is ide1 master)\n"
+ "-boot [a|c|d] boot on floppy (a), hard disk (c) or CD-ROM (d)\n"
+ "-snapshot write to temporary files instead of disk image files\n"
+ "-m megs set virtual RAM size to megs MB [default=%d]\n"
+ "-nographic disable graphical output and redirect serial I/Os to console\n"
+#ifdef CONFIG_VNC
+ "-vnc use vnc instead of sdl\n"
+#ifdef CONFIG_SDL
+ "-vnc-and-sdl use vnc and sdl simultaneously\n"
+#endif
+#endif
+ "-k <language> use keyboard layout (for example \"fr\" for french)\n"
+ "-enable-audio enable audio support\n"
+ "-localtime set the real time clock to local time [default=utc]\n"
+ "-full-screen start in full screen\n"
+#ifdef TARGET_PPC
+ "-prep Simulate a PREP system (default is PowerMAC)\n"
+ "-g WxH[xDEPTH] Set the initial VGA graphic mode\n"
+#endif
+ "\n"
+ "Network options:\n"
+ "-nics n simulate 'n' network cards [default=1]\n"
+ "-macaddr addr set the mac address of the first interface\n"
+ "-n script set tap/tun network init script [default=%s]\n"
+ "-tun-fd fd use this fd as already opened tap/tun interface\n"
+#ifdef CONFIG_SLIRP
+ "-user-net use user mode network stack [default if no tap/tun script]\n"
+ "-tftp prefix allow tftp access to files starting with prefix [-user-net]\n"
+#ifndef _WIN32
+ "-smb dir allow SMB access to files in 'dir' [-user-net]\n"
+#endif
+ "-redir [tcp|udp]:host-port:[guest-host]:guest-port\n"
+ " redirect TCP or UDP connections from host to guest [-user-net]\n"
+#endif
+ "-dummy-net use dummy network stack\n"
+ "\n"
+ "Linux boot specific:\n"
+ "-kernel bzImage use 'bzImage' as kernel image\n"
+ "-append cmdline use 'cmdline' as kernel command line\n"
+ "-initrd file use 'file' as initial ram disk\n"
+ "\n"
+ "Debug/Expert options:\n"
+ "-monitor dev redirect the monitor to char device 'dev'\n"
+ "-serial dev redirect the serial port to char device 'dev'\n"
+ "-S freeze CPU at startup (use 'c' to start execution)\n"
+ "-s wait gdb connection to port %d\n"
+ "-p port ioreq port for xen\n"
+ "-d domain domain that we're serving\n"
+ "-hdachs c,h,s force hard disk 0 geometry (usually qemu can guess it)\n"
+ "-L path set the directory for the BIOS and VGA BIOS\n"
+#ifdef USE_CODE_COPY
+ "-no-code-copy disable code copy acceleration\n"
+#endif
+#ifdef TARGET_I386
+ "-isa simulate an ISA-only system (default is PCI system)\n"
+ "-std-vga simulate a standard VGA card with VESA Bochs Extensions\n"
+ " (default is CL-GD5446 PCI VGA)\n"
+#endif
+ "-loadvm file start right away with a saved state (loadvm in monitor)\n"
+ "\n"
+ "During emulation, the following keys are useful:\n"
+ "ctrl-alt-f toggle full screen\n"
+ "ctrl-alt-n switch to virtual console 'n'\n"
+ "ctrl-alt toggle mouse and keyboard grab\n"
+ "\n"
+ "When using -nographic, press 'ctrl-a h' to get some help.\n"
+ ,
+#ifdef CONFIG_SOFTMMU
+ "qemu",
+#else
+ "qemu-fast",
+#endif
+ DEFAULT_RAM_SIZE,
+ DEFAULT_NETWORK_SCRIPT,
+ DEFAULT_GDBSTUB_PORT);
+#ifndef CONFIG_SOFTMMU
+ printf("\n"
+ "NOTE: this version of QEMU is faster but it needs slightly patched OSes to\n"
+ "work. Please use the 'qemu' executable to have a more accurate (but slower)\n"
+ "PC emulation.\n");
+#endif
+ exit(1);
+}
+
+#define HAS_ARG 0x0001
+
+enum {
+ QEMU_OPTION_h,
+
+ QEMU_OPTION_fda,
+ QEMU_OPTION_fdb,
+ QEMU_OPTION_hda,
+ QEMU_OPTION_hdb,
+ QEMU_OPTION_hdc,
+ QEMU_OPTION_hdd,
+ QEMU_OPTION_cdrom,
+ QEMU_OPTION_boot,
+ QEMU_OPTION_snapshot,
+ QEMU_OPTION_m,
+ QEMU_OPTION_nographic,
+#ifdef CONFIG_VNC
+ QEMU_OPTION_vnc,
+#ifdef CONFIG_SDL
+ QEMU_OPTION_vnc_and_sdl,
+#endif
+#endif
+ QEMU_OPTION_enable_audio,
+
+ QEMU_OPTION_nics,
+ QEMU_OPTION_macaddr,
+ QEMU_OPTION_n,
+ QEMU_OPTION_tun_fd,
+ QEMU_OPTION_user_net,
+ QEMU_OPTION_tftp,
+ QEMU_OPTION_smb,
+ QEMU_OPTION_redir,
+ QEMU_OPTION_dummy_net,
+
+ QEMU_OPTION_kernel,
+ QEMU_OPTION_append,
+ QEMU_OPTION_initrd,
+
+ QEMU_OPTION_S,
+ QEMU_OPTION_s,
+ QEMU_OPTION_p,
+ QEMU_OPTION_d,
+ QEMU_OPTION_l,
+ QEMU_OPTION_hdachs,
+ QEMU_OPTION_L,
+ QEMU_OPTION_no_code_copy,
+ QEMU_OPTION_pci,
+ QEMU_OPTION_isa,
+ QEMU_OPTION_prep,
+ QEMU_OPTION_k,
+ QEMU_OPTION_localtime,
+ QEMU_OPTION_cirrusvga,
+ QEMU_OPTION_g,
+ QEMU_OPTION_std_vga,
+ QEMU_OPTION_monitor,
+ QEMU_OPTION_serial,
+ QEMU_OPTION_loadvm,
+ QEMU_OPTION_full_screen,
+};
+
+typedef struct QEMUOption {
+ const char *name;
+ int flags;
+ int index;
+} QEMUOption;
+
+const QEMUOption qemu_options[] = {
+ { "h", 0, QEMU_OPTION_h },
+
+ { "fda", HAS_ARG, QEMU_OPTION_fda },
+ { "fdb", HAS_ARG, QEMU_OPTION_fdb },
+ { "hda", HAS_ARG, QEMU_OPTION_hda },
+ { "hdb", HAS_ARG, QEMU_OPTION_hdb },
+ { "hdc", HAS_ARG, QEMU_OPTION_hdc },
+ { "hdd", HAS_ARG, QEMU_OPTION_hdd },
+ { "cdrom", HAS_ARG, QEMU_OPTION_cdrom },
+ { "boot", HAS_ARG, QEMU_OPTION_boot },
+ { "snapshot", 0, QEMU_OPTION_snapshot },
+ { "m", HAS_ARG, QEMU_OPTION_m },
+ { "nographic", 0, QEMU_OPTION_nographic },
+#ifdef CONFIG_VNC
+ { "vnc", 0, QEMU_OPTION_vnc },
+#ifdef CONFIG_SDL
+ { "vnc-and-sdl", 0, QEMU_OPTION_vnc_and_sdl },
+#endif
+#endif
+ { "k", HAS_ARG, QEMU_OPTION_k },
+ { "enable-audio", 0, QEMU_OPTION_enable_audio },
+
+ { "nics", HAS_ARG, QEMU_OPTION_nics},
+ { "macaddr", HAS_ARG, QEMU_OPTION_macaddr},
+ { "n", HAS_ARG, QEMU_OPTION_n },
+ { "tun-fd", HAS_ARG, QEMU_OPTION_tun_fd },
+#ifdef CONFIG_SLIRP
+ { "user-net", 0, QEMU_OPTION_user_net },
+ { "tftp", HAS_ARG, QEMU_OPTION_tftp },
+#ifndef _WIN32
+ { "smb", HAS_ARG, QEMU_OPTION_smb },
+#endif
+ { "redir", HAS_ARG, QEMU_OPTION_redir },
+#endif
+ { "dummy-net", 0, QEMU_OPTION_dummy_net },
+
+ { "kernel", HAS_ARG, QEMU_OPTION_kernel },
+ { "append", HAS_ARG, QEMU_OPTION_append },
+ { "initrd", HAS_ARG, QEMU_OPTION_initrd },
+
+ { "S", 0, QEMU_OPTION_S },
+ { "s", 0, QEMU_OPTION_s },
+ { "p", HAS_ARG, QEMU_OPTION_p },
+ { "d", HAS_ARG, QEMU_OPTION_d },
+ { "l", HAS_ARG, QEMU_OPTION_l },
+ { "hdachs", HAS_ARG, QEMU_OPTION_hdachs },
+ { "L", HAS_ARG, QEMU_OPTION_L },
+ { "no-code-copy", 0, QEMU_OPTION_no_code_copy },
+#ifdef TARGET_PPC
+ { "prep", 0, QEMU_OPTION_prep },
+ { "g", 1, QEMU_OPTION_g },
+#endif
+ { "localtime", 0, QEMU_OPTION_localtime },
+ { "isa", 0, QEMU_OPTION_isa },
+ { "std-vga", 0, QEMU_OPTION_std_vga },
+ { "monitor", 1, QEMU_OPTION_monitor },
+ { "serial", 1, QEMU_OPTION_serial },
+ { "loadvm", HAS_ARG, QEMU_OPTION_loadvm },
+ { "full-screen", 0, QEMU_OPTION_full_screen },
+
+ /* temporary options */
+ { "pci", 0, QEMU_OPTION_pci },
+ { "cirrusvga", 0, QEMU_OPTION_cirrusvga },
+ { NULL },
+};
+
+#if defined (TARGET_I386) && defined(USE_CODE_COPY)
+
+/* this stack is only used during signal handling */
+#define SIGNAL_STACK_SIZE 32768
+
+static uint8_t *signal_stack;
+
+#endif
+
+#define NET_IF_TUN 0
+#define NET_IF_USER 1
+#define NET_IF_DUMMY 2
+
+int main(int argc, char **argv)
+{
+#ifdef CONFIG_GDBSTUB
+ int use_gdbstub, gdbstub_port;
+#endif
+ int i, has_cdrom;
+ int snapshot, linux_boot;
+ CPUState *env;
+ const char *initrd_filename;
+ const char *hd_filename[MAX_DISKS], *fd_filename[MAX_FD];
+ const char *kernel_filename, *kernel_cmdline;
+ DisplayState *ds = &display_state;
+ int cyls, heads, secs;
+ int start_emulation = 1;
+ uint8_t macaddr[6];
+ int net_if_type, nb_tun_fds, tun_fds[MAX_NICS];
+ int optind;
+ const char *r, *optarg;
+ CharDriverState *monitor_hd;
+ char monitor_device[128];
+ char serial_devices[MAX_SERIAL_PORTS][128];
+ int serial_device_index;
+ const char *loadvm = NULL;
+ unsigned long nr_pages, *page_array;
+ extern void *shared_page;
+ /* change the qemu-dm to daemon, just like bochs dm */
+// daemon(0, 0);
+
+#if !defined(CONFIG_SOFTMMU)
+ /* we never want that malloc() uses mmap() */
+ mallopt(M_MMAP_THRESHOLD, 4096 * 1024);
+#endif
+ initrd_filename = NULL;
+ for(i = 0; i < MAX_FD; i++)
+ fd_filename[i] = NULL;
+ for(i = 0; i < MAX_DISKS; i++)
+ hd_filename[i] = NULL;
+ ram_size = DEFAULT_RAM_SIZE * 1024 * 1024;
+ vga_ram_size = VGA_RAM_SIZE;
+ bios_size = BIOS_SIZE;
+ pstrcpy(network_script, sizeof(network_script), DEFAULT_NETWORK_SCRIPT);
+#ifdef CONFIG_GDBSTUB
+ use_gdbstub = 0;
+ gdbstub_port = DEFAULT_GDBSTUB_PORT;
+#endif
+ snapshot = 0;
+ nographic = 0;
+ usevnc = 0;
+ kernel_filename = NULL;
+ kernel_cmdline = "";
+ has_cdrom = 1;
+ cyls = heads = secs = 0;
+ pstrcpy(monitor_device, sizeof(monitor_device), "vc");
+
+ pstrcpy(serial_devices[0], sizeof(serial_devices[0]), "vc");
+ for(i = 1; i < MAX_SERIAL_PORTS; i++)
+ serial_devices[i][0] = '\0';
+ serial_device_index = 0;
+
+ nb_tun_fds = 0;
+ net_if_type = -1;
+ nb_nics = 1;
+ /* default mac address of the first network interface */
+ macaddr[0] = 0x52;
+ macaddr[1] = 0x54;
+ macaddr[2] = 0x00;
+ macaddr[3] = 0x12;
+ macaddr[4] = 0x34;
+ macaddr[5] = 0x56;
+
+ optind = 1;
+ for(;;) {
+ if (optind >= argc)
+ break;
+ r = argv[optind];
+ if (r[0] != '-') {
+ hd_filename[0] = argv[optind++];
+ } else {
+ const QEMUOption *popt;
+
+ optind++;
+ popt = qemu_options;
+ for(;;) {
+ if (!popt->name) {
+ fprintf(stderr, "%s: invalid option -- '%s'\n",
+ argv[0], r);
+ exit(1);
+ }
+ if (!strcmp(popt->name, r + 1))
+ break;
+ popt++;
+ }
+ if (popt->flags & HAS_ARG) {
+ if (optind >= argc) {
+ fprintf(stderr, "%s: option '%s' requires an argument\n",
+ argv[0], r);
+ exit(1);
+ }
+ optarg = argv[optind++];
+ } else {
+ optarg = NULL;
+ }
+
+ switch(popt->index) {
+ case QEMU_OPTION_initrd:
+ initrd_filename = optarg;
+ break;
+ case QEMU_OPTION_hda:
+ hd_filename[0] = optarg;
+ break;
+ case QEMU_OPTION_hdb:
+ hd_filename[1] = optarg;
+ break;
+ case QEMU_OPTION_snapshot:
+ snapshot = 1;
+ break;
+ case QEMU_OPTION_hdachs:
+ {
+ const char *p;
+ p = optarg;
+ cyls = strtol(p, (char **)&p, 0);
+ if (*p != ',')
+ goto chs_fail;
+ p++;
+ heads = strtol(p, (char **)&p, 0);
+ if (*p != ',')
+ goto chs_fail;
+ p++;
+ secs = strtol(p, (char **)&p, 0);
+ if (*p != '\0') {
+ chs_fail:
+ cyls = 0;
+ }
+ }
+ break;
+ case QEMU_OPTION_nographic:
+ pstrcpy(monitor_device, sizeof(monitor_device), "stdio");
+ pstrcpy(serial_devices[0], sizeof(serial_devices[0]), "stdio");
+ nographic = 1;
+ break;
+#ifdef CONFIG_VNC
+ case QEMU_OPTION_vnc:
+ usevnc = 1;
+ break;
+#ifdef CONFIG_SDL
+ case QEMU_OPTION_vnc_and_sdl:
+ usevnc = 2;
+ break;
+#endif
+#endif
+ case QEMU_OPTION_kernel:
+ kernel_filename = optarg;
+ break;
+ case QEMU_OPTION_append:
+ kernel_cmdline = optarg;
+ break;
+ case QEMU_OPTION_tun_fd:
+ {
+ const char *p;
+ int fd;
+ net_if_type = NET_IF_TUN;
+ if (nb_tun_fds < MAX_NICS) {
+ fd = strtol(optarg, (char **)&p, 0);
+ if (*p != '\0') {
+ fprintf(stderr, "qemu: invalid fd for network interface %d\n", nb_tun_fds);
+ exit(1);
+ }
+ tun_fds[nb_tun_fds++] = fd;
+ }
+ }
+ break;
+ case QEMU_OPTION_hdc:
+ hd_filename[2] = optarg;
+ has_cdrom = 0;
+ break;
+ case QEMU_OPTION_hdd:
+ hd_filename[3] = optarg;
+ break;
+ case QEMU_OPTION_cdrom:
+ hd_filename[2] = optarg;
+ has_cdrom = 1;
+ break;
+ case QEMU_OPTION_boot:
+ boot_device = optarg[0];
+ if (boot_device != 'a' &&
+ boot_device != 'c' && boot_device != 'd') {
+ fprintf(stderr, "qemu: invalid boot device '%c'\n", boot_device);
+ exit(1);
+ }
+ break;
+ case QEMU_OPTION_fda:
+ fd_filename[0] = optarg;
+ break;
+ case QEMU_OPTION_fdb:
+ fd_filename[1] = optarg;
+ break;
+ case QEMU_OPTION_nics:
+ nb_nics = atoi(optarg);
+ if (nb_nics < 0 || nb_nics > MAX_NICS) {
+ fprintf(stderr, "qemu: invalid number of network interfaces\n");
+ exit(1);
+ }
+ break;
+ case QEMU_OPTION_macaddr:
+ {
+ const char *p;
+ int i;
+ p = optarg;
+ for(i = 0; i < 6; i++) {
+ macaddr[i] = strtol(p, (char **)&p, 16);
+ if (i == 5) {
+ if (*p != '\0')
+ goto macaddr_error;
+ } else {
+ if (*p != ':') {
+ macaddr_error:
+ fprintf(stderr, "qemu: invalid syntax for ethernet address\n");
+ exit(1);
+ }
+ p++;
+ }
+ }
+ }
+ break;
+#ifdef CONFIG_SLIRP
+ case QEMU_OPTION_tftp:
+ tftp_prefix = optarg;
+ break;
+#ifndef _WIN32
+ case QEMU_OPTION_smb:
+ net_slirp_smb(optarg);
+ break;
+#endif
+ case QEMU_OPTION_user_net:
+ net_if_type = NET_IF_USER;
+ break;
+ case QEMU_OPTION_redir:
+ net_slirp_redir(optarg);
+ break;
+#endif
+ case QEMU_OPTION_dummy_net:
+ net_if_type = NET_IF_DUMMY;
+ break;
+ case QEMU_OPTION_enable_audio:
+ audio_enabled = 1;
+ break;
+ case QEMU_OPTION_h:
+ help();
+ break;
+ case QEMU_OPTION_m:
+ ram_size = atoi(optarg) * 1024 * 1024;
+ if (ram_size <= 0)
+ help();
+ break;
+ case QEMU_OPTION_d:
+ {
+ domid = atoi(optarg);
+ printf("domid: %d\n", domid);
+ }
+ break;
+
+ case QEMU_OPTION_p:
+ {
+ extern short ioreq_port;
+ ioreq_port = atoi(optarg);
+ printf("port: %d\n", ioreq_port);
+ }
+ break;
+ case QEMU_OPTION_l:
+ {
+ int mask;
+ mask = cpu_str_to_log_mask(optarg);
+ printf("mask: %x\n", mask);
+ cpu_set_log(mask);
+ }
+ break;
+ case QEMU_OPTION_n:
+ pstrcpy(network_script, sizeof(network_script), optarg);
+ break;
+#ifdef CONFIG_GDBSTUB
+ case QEMU_OPTION_s:
+ use_gdbstub = 1;
+ break;
+#endif
+ case QEMU_OPTION_L:
+ bios_dir = optarg;
+ break;
+ case QEMU_OPTION_S:
+ start_emulation = 0;
+ break;
+ case QEMU_OPTION_pci:
+ pci_enabled = 1;
+ break;
+ case QEMU_OPTION_isa:
+ pci_enabled = 0;
+ break;
+ case QEMU_OPTION_prep:
+ prep_enabled = 1;
+ break;
+ case QEMU_OPTION_k:
+ keyboard_layout = optarg;
+ break;
+ case QEMU_OPTION_localtime:
+ rtc_utc = 0;
+ break;
+ case QEMU_OPTION_cirrusvga:
+ cirrus_vga_enabled = 1;
+ break;
+ case QEMU_OPTION_std_vga:
+ cirrus_vga_enabled = 0;
+ break;
+ case QEMU_OPTION_g:
+ {
+ const char *p;
+ int w, h, depth;
+ p = optarg;
+ w = strtol(p, (char **)&p, 10);
+ if (w <= 0) {
+ graphic_error:
+ fprintf(stderr, "qemu: invalid resolution or depth\n");
+ exit(1);
+ }
+ if (*p != 'x')
+ goto graphic_error;
+ p++;
+ h = strtol(p, (char **)&p, 10);
+ if (h <= 0)
+ goto graphic_error;
+ if (*p == 'x') {
+ p++;
+ depth = strtol(p, (char **)&p, 10);
+ if (depth != 8 && depth != 15 && depth != 16 &&
+ depth != 24 && depth != 32)
+ goto graphic_error;
+ } else if (*p == '\0') {
+ depth = graphic_depth;
+ } else {
+ goto graphic_error;
+ }
+
+ graphic_width = w;
+ graphic_height = h;
+ graphic_depth = depth;
+ }
+ break;
+ case QEMU_OPTION_monitor:
+ pstrcpy(monitor_device, sizeof(monitor_device), optarg);
+ break;
+ case QEMU_OPTION_serial:
+ if (serial_device_index >= MAX_SERIAL_PORTS) {
+ fprintf(stderr, "qemu: too many serial ports\n");
+ exit(1);
+ }
+ pstrcpy(serial_devices[serial_device_index],
+ sizeof(serial_devices[0]), optarg);
+ serial_device_index++;
+ break;
+ case QEMU_OPTION_loadvm:
+ loadvm = optarg;
+ break;
+ case QEMU_OPTION_full_screen:
+ full_screen = 1;
+ break;
+ }
+ }
+ }
+
+ linux_boot = (kernel_filename != NULL);
+
+ if (!linux_boot && hd_filename[0] == '\0' && hd_filename[2] == '\0' &&
+ fd_filename[0] == '\0')
+ help();
+
+ /* boot to cd by default if no hard disk */
+ if (hd_filename[0] == '\0' && boot_device == 'c') {
+ if (fd_filename[0] != '\0')
+ boot_device = 'a';
+ else
+ boot_device = 'd';
+ }
+
+#if !defined(CONFIG_SOFTMMU)
+ /* must avoid mmap() usage of glibc by setting a buffer "by hand" */
+ {
+ static uint8_t stdout_buf[4096];
+ setvbuf(stdout, stdout_buf, _IOLBF, sizeof(stdout_buf));
+ }
+#else
+ setvbuf(stdout, NULL, _IOLBF, 0);
+#endif
+
+ /* init host network redirectors */
+ if (net_if_type == -1) {
+ net_if_type = NET_IF_TUN;
+#if defined(CONFIG_SLIRP)
+ if (access(network_script, R_OK) < 0) {
+ net_if_type = NET_IF_USER;
+ }
+#endif
+ }
+
+ for(i = 0; i < nb_nics; i++) {
+ NetDriverState *nd = &nd_table[i];
+ nd->index = i;
+ /* init virtual mac address */
+ nd->macaddr[0] = macaddr[0];
+ nd->macaddr[1] = macaddr[1];
+ nd->macaddr[2] = macaddr[2];
+ nd->macaddr[3] = macaddr[3];
+ nd->macaddr[4] = macaddr[4];
+ nd->macaddr[5] = macaddr[5] + i;
+ switch(net_if_type) {
+#if defined(CONFIG_SLIRP)
+ case NET_IF_USER:
+ net_slirp_init(nd);
+ break;
+#endif
+#if !defined(_WIN32)
+ case NET_IF_TUN:
+ if (i < nb_tun_fds) {
+ net_fd_init(nd, tun_fds[i]);
+ } else {
+ if (net_tun_init(nd) < 0)
+ net_dummy_init(nd);
+ }
+ break;
+#endif
+ case NET_IF_DUMMY:
+ default:
+ net_dummy_init(nd);
+ break;
+ }
+ }
+
+ /* init the memory */
+ phys_ram_size = ram_size + vga_ram_size + bios_size;
+
+ #define PAGE_SHIFT 12
+ #define PAGE_SIZE (1 << PAGE_SHIFT)
+
+ nr_pages = ram_size/PAGE_SIZE;
+ xc_handle = xc_interface_open();
+
+ if ( (page_array = (unsigned long *)
+ malloc(nr_pages * sizeof(unsigned long))) == NULL)
+ {
+ perror("malloc");
+ exit(-1);
+ }
+
+ if ( xc_get_pfn_list(xc_handle, domid, page_array, nr_pages) != nr_pages )
+ {
+ perror("xc_get_pfn_list");
+ exit(-1);
+ }
+
+ if ((phys_ram_base = xc_map_foreign_batch(xc_handle, domid,
+ PROT_READ|PROT_WRITE,
+ page_array,
+ nr_pages - 1)) == 0) {
+ perror("xc_map_foreign_batch");
+ exit(-1);
+ }
+
+
+ shared_page = xc_map_foreign_range(xc_handle, domid, PAGE_SIZE,
+ PROT_READ|PROT_WRITE,
+ page_array[nr_pages - 1]);
+
+ /* we always create the cdrom drive, even if no disk is there */
+ bdrv_init();
+ if (has_cdrom) {
+ bs_table[2] = bdrv_new("cdrom");
+ bdrv_set_type_hint(bs_table[2], BDRV_TYPE_CDROM);
+ }
+
+ /* open the virtual block devices */
+ for(i = 0; i < MAX_DISKS; i++) {
+ if (hd_filename[i]) {
+ if (!bs_table[i]) {
+ char buf[64];
+ snprintf(buf, sizeof(buf), "hd%c", i + 'a');
+ bs_table[i] = bdrv_new(buf);
+ }
+ if (bdrv_open(bs_table[i], hd_filename[i], snapshot) < 0) {
+ fprintf(stderr, "qemu: could not open hard disk image '%s'\n",
+ hd_filename[i]);
+ exit(1);
+ }
+ if (i == 0 && cyls != 0)
+ bdrv_set_geometry_hint(bs_table[i], cyls, heads, secs);
+ }
+ }
+
+ /* we always create at least one floppy disk */
+ fd_table[0] = bdrv_new("fda");
+ bdrv_set_type_hint(fd_table[0], BDRV_TYPE_FLOPPY);
+
+ for(i = 0; i < MAX_FD; i++) {
+ if (fd_filename[i]) {
+ if (!fd_table[i]) {
+ char buf[64];
+ snprintf(buf, sizeof(buf), "fd%c", i + 'a');
+ fd_table[i] = bdrv_new(buf);
+ bdrv_set_type_hint(fd_table[i], BDRV_TYPE_FLOPPY);
+ }
+ if (fd_filename[i] != '\0') {
+ if (bdrv_open(fd_table[i], fd_filename[i], snapshot) < 0) {
+ fprintf(stderr, "qemu: could not open floppy disk image '%s'\n",
+ fd_filename[i]);
+ exit(1);
+ }
+ }
+ }
+ }
+
+ /* init CPU state */
+ env = cpu_init();
+ global_env = env;
+ cpu_single_env = env;
+
+ init_ioports();
+ cpu_calibrate_ticks();
+
+ /* terminal init */
+ if (nographic) {
+ dumb_display_init(ds);
+ } else {
+ if (usevnc) {
+#ifdef CONFIG_VNC
+ vnc_display_init(ds, (usevnc==2));
+#else
+ perror("qemu not configured with vnc support");
+#endif
+ } else {
+#ifdef CONFIG_SDL
+ sdl_display_init(ds, full_screen);
+#else
+ dumb_display_init(ds);
+#endif
+ }
+ }
+
+ vga_console = graphic_console_init(ds);
+
+ monitor_hd = qemu_chr_open(monitor_device);
+ if (!monitor_hd) {
+ fprintf(stderr, "qemu: could not open monitor device '%s'\n", monitor_device);
+ exit(1);
+ }
+ monitor_init(monitor_hd, !nographic);
+
+ for(i = 0; i < MAX_SERIAL_PORTS; i++) {
+ if (serial_devices[i][0] != '\0') {
+ serial_hds[i] = qemu_chr_open(serial_devices[i]);
+ if (!serial_hds[i]) {
+ fprintf(stderr, "qemu: could not open serial device '%s'\n",
+ serial_devices[i]);
+ exit(1);
+ }
+ if (!strcmp(serial_devices[i], "vc"))
+ qemu_chr_printf(serial_hds[i], "serial%d console\n", i);
+ }
+ }
+
+ /* setup cpu signal handlers for MMU / self modifying code handling */
+#if !defined(CONFIG_SOFTMMU)
+
+#if defined (TARGET_I386) && defined(USE_CODE_COPY)
+ {
+ stack_t stk;
+ signal_stack = memalign(16, SIGNAL_STACK_SIZE);
+ stk.ss_sp = signal_stack;
+ stk.ss_size = SIGNAL_STACK_SIZE;
+ stk.ss_flags = 0;
+
+ if (sigaltstack(&stk, NULL) < 0) {
+ perror("sigaltstack");
+ exit(1);
+ }
+ }
+#endif
+ {
+ struct sigaction act;
+
+ sigfillset(&act.sa_mask);
+ act.sa_flags = SA_SIGINFO;
+#if defined (TARGET_I386) && defined(USE_CODE_COPY)
+ act.sa_flags |= SA_ONSTACK;
+#endif
+ act.sa_sigaction = host_segv_handler;
+ sigaction(SIGSEGV, &act, NULL);
+ sigaction(SIGBUS, &act, NULL);
+#if defined (TARGET_I386) && defined(USE_CODE_COPY)
+ sigaction(SIGFPE, &act, NULL);
+#endif
+ }
+#endif
+
+#ifndef _WIN32
+ {
+ struct sigaction act;
+ sigfillset(&act.sa_mask);
+ act.sa_flags = 0;
+ act.sa_handler = SIG_IGN;
+ sigaction(SIGPIPE, &act, NULL);
+ }
+#endif
+ init_timers();
+
+#if defined(TARGET_I386)
+ pc_init(ram_size, vga_ram_size, boot_device,
+ ds, fd_filename, snapshot,
+ kernel_filename, kernel_cmdline, initrd_filename);
+#elif defined(TARGET_PPC)
+ ppc_init(ram_size, vga_ram_size, boot_device,
+ ds, fd_filename, snapshot,
+ kernel_filename, kernel_cmdline, initrd_filename);
+#elif defined(TARGET_SPARC)
+ sun4m_init(ram_size, vga_ram_size, boot_device,
+ ds, fd_filename, snapshot,
+ kernel_filename, kernel_cmdline, initrd_filename);
+#endif
+
+ gui_timer = qemu_new_timer(rt_clock, gui_update, NULL);
+ qemu_mod_timer(gui_timer, qemu_get_clock(rt_clock));
+
+ polling_timer = qemu_new_timer(rt_clock, polling_handler, NULL);
+ qemu_mod_timer(polling_timer, qemu_get_clock(rt_clock));
+
+#ifdef CONFIG_GDBSTUB
+ if (use_gdbstub) {
+ if (gdbserver_start(gdbstub_port) < 0) {
+ fprintf(stderr, "Could not open gdbserver socket on port %d\n",
+ gdbstub_port);
+ exit(1);
+ } else {
+ printf("Waiting gdb connection on port %d\n", gdbstub_port);
+ }
+ } else
+#endif
+ if (loadvm)
+ qemu_loadvm(loadvm);
+
+ {
+ /* XXX: simplify init */
+ if (start_emulation) {
+ vm_start();
+ }
+ }
+ main_loop();
+ quit_timers();
+ return 0;
+}
--- /dev/null
+/*
+ * QEMU System Emulator header
+ *
+ * Copyright (c) 2003 Fabrice Bellard
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#ifndef VL_H
+#define VL_H
+
+/* we put basic includes here to avoid repeating them in device drivers */
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <time.h>
+#include <ctype.h>
+#include <errno.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+
+#ifndef O_LARGEFILE
+#define O_LARGEFILE 0
+#endif
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+#ifdef _WIN32
+#define lseek _lseeki64
+#define ENOTSUP 4096
+/* XXX: find 64 bit version */
+#define ftruncate chsize
+
+static inline char *realpath(const char *path, char *resolved_path)
+{
+ _fullpath(resolved_path, path, _MAX_PATH);
+ return resolved_path;
+}
+#endif
+
+#ifdef QEMU_TOOL
+
+/* we use QEMU_TOOL in the command line tools which do not depend on
+ the target CPU type */
+#include "config-host.h"
+#include <setjmp.h>
+#include "osdep.h"
+#include "bswap.h"
+
+#else
+
+#include "cpu.h"
+
+#endif /* !defined(QEMU_TOOL) */
+
+#ifndef glue
+#define xglue(x, y) x ## y
+#define glue(x, y) xglue(x, y)
+#define stringify(s) tostring(s)
+#define tostring(s) #s
+#endif
+
+/* vl.c */
+uint64_t muldiv64(uint64_t a, uint32_t b, uint32_t c);
+
+void hw_error(const char *fmt, ...);
+
+int get_image_size(const char *filename);
+int load_image(const char *filename, uint8_t *addr);
+extern const char *bios_dir;
+
+void pstrcpy(char *buf, int buf_size, const char *str);
+char *pstrcat(char *buf, int buf_size, const char *s);
+int strstart(const char *str, const char *val, const char **ptr);
+
+extern int vm_running;
+
+typedef void VMStopHandler(void *opaque, int reason);
+
+int qemu_add_vm_stop_handler(VMStopHandler *cb, void *opaque);
+void qemu_del_vm_stop_handler(VMStopHandler *cb, void *opaque);
+
+void vm_start(void);
+void vm_stop(int reason);
+
+typedef void QEMUResetHandler(void *opaque);
+
+void qemu_register_reset(QEMUResetHandler *func, void *opaque);
+void qemu_system_reset_request(void);
+void qemu_system_shutdown_request(void);
+
+void main_loop_wait(int timeout);
+
+extern int audio_enabled;
+extern int sb16_enabled;
+extern int adlib_enabled;
+extern int gus_enabled;
+extern int ram_size;
+extern int bios_size;
+extern int rtc_utc;
+extern int cirrus_vga_enabled;
+extern int graphic_width;
+extern int graphic_height;
+extern int graphic_depth;
+
+/* XXX: make it dynamic */
+#if defined (TARGET_PPC)
+#define BIOS_SIZE (512 * 1024)
+#else
+#define BIOS_SIZE ((256 + 64) * 1024)
+#endif
+
+/* keyboard/mouse support */
+
+#define MOUSE_EVENT_LBUTTON 0x01
+#define MOUSE_EVENT_RBUTTON 0x02
+#define MOUSE_EVENT_MBUTTON 0x04
+
+typedef void QEMUPutKBDEvent(void *opaque, int keycode);
+typedef void QEMUPutMouseEvent(void *opaque, int dx, int dy, int dz, int buttons_state);
+
+void qemu_add_kbd_event_handler(QEMUPutKBDEvent *func, void *opaque);
+void qemu_add_mouse_event_handler(QEMUPutMouseEvent *func, void *opaque);
+
+void kbd_put_keycode(int keycode);
+void kbd_mouse_event(int dx, int dy, int dz, int buttons_state);
+
+/* keysym is a unicode code except for special keys (see QEMU_KEY_xxx
+ constants) */
+#define QEMU_KEY_ESC1(c) ((c) | 0xe100)
+#define QEMU_KEY_BACKSPACE 0x007f
+#define QEMU_KEY_UP QEMU_KEY_ESC1('A')
+#define QEMU_KEY_DOWN QEMU_KEY_ESC1('B')
+#define QEMU_KEY_RIGHT QEMU_KEY_ESC1('C')
+#define QEMU_KEY_LEFT QEMU_KEY_ESC1('D')
+#define QEMU_KEY_HOME QEMU_KEY_ESC1(1)
+#define QEMU_KEY_END QEMU_KEY_ESC1(4)
+#define QEMU_KEY_PAGEUP QEMU_KEY_ESC1(5)
+#define QEMU_KEY_PAGEDOWN QEMU_KEY_ESC1(6)
+#define QEMU_KEY_DELETE QEMU_KEY_ESC1(3)
+
+#define QEMU_KEY_CTRL_UP 0xe400
+#define QEMU_KEY_CTRL_DOWN 0xe401
+#define QEMU_KEY_CTRL_LEFT 0xe402
+#define QEMU_KEY_CTRL_RIGHT 0xe403
+#define QEMU_KEY_CTRL_HOME 0xe404
+#define QEMU_KEY_CTRL_END 0xe405
+#define QEMU_KEY_CTRL_PAGEUP 0xe406
+#define QEMU_KEY_CTRL_PAGEDOWN 0xe407
+
+void kbd_put_keysym(int keysym);
+
+/* async I/O support */
+
+typedef void IOReadHandler(void *opaque, const uint8_t *buf, int size);
+typedef int IOCanRWHandler(void *opaque);
+
+int qemu_add_fd_read_handler(int fd, IOCanRWHandler *fd_can_read,
+ IOReadHandler *fd_read, void *opaque);
+void qemu_del_fd_read_handler(int fd);
+
+/* character device */
+
+#define CHR_EVENT_BREAK 0 /* serial break char */
+#define CHR_EVENT_FOCUS 1 /* focus to this terminal (modal input needed) */
+
+typedef void IOEventHandler(void *opaque, int event);
+
+typedef struct CharDriverState {
+ int (*chr_write)(struct CharDriverState *s, const uint8_t *buf, int len);
+ void (*chr_add_read_handler)(struct CharDriverState *s,
+ IOCanRWHandler *fd_can_read,
+ IOReadHandler *fd_read, void *opaque);
+ IOEventHandler *chr_event;
+ void (*chr_send_event)(struct CharDriverState *chr, int event);
+ void *opaque;
+} CharDriverState;
+
+void qemu_chr_printf(CharDriverState *s, const char *fmt, ...);
+int qemu_chr_write(CharDriverState *s, const uint8_t *buf, int len);
+void qemu_chr_send_event(CharDriverState *s, int event);
+void qemu_chr_add_read_handler(CharDriverState *s,
+ IOCanRWHandler *fd_can_read,
+ IOReadHandler *fd_read, void *opaque);
+void qemu_chr_add_event_handler(CharDriverState *s, IOEventHandler *chr_event);
+
+/* consoles */
+
+typedef struct DisplayState DisplayState;
+typedef struct TextConsole TextConsole;
+
+extern TextConsole *vga_console;
+
+TextConsole *graphic_console_init(DisplayState *ds);
+int is_active_console(TextConsole *s);
+CharDriverState *text_console_init(DisplayState *ds);
+void console_select(unsigned int index);
+
+/* serial ports */
+
+#define MAX_SERIAL_PORTS 4
+
+extern CharDriverState *serial_hds[MAX_SERIAL_PORTS];
+
+/* network redirectors support */
+
+#define MAX_NICS 8
+
+typedef struct NetDriverState {
+ int index; /* index number in QEMU */
+ uint8_t macaddr[6];
+ char ifname[16];
+ void (*send_packet)(struct NetDriverState *nd,
+ const uint8_t *buf, int size);
+ void (*add_read_packet)(struct NetDriverState *nd,
+ IOCanRWHandler *fd_can_read,
+ IOReadHandler *fd_read, void *opaque);
+ /* tun specific data */
+ int fd;
+ /* slirp specific data */
+} NetDriverState;
+
+extern int nb_nics;
+extern NetDriverState nd_table[MAX_NICS];
+
+void qemu_send_packet(NetDriverState *nd, const uint8_t *buf, int size);
+void qemu_add_read_packet(NetDriverState *nd, IOCanRWHandler *fd_can_read,
+ IOReadHandler *fd_read, void *opaque);
+
+/* timers */
+
+typedef struct QEMUClock QEMUClock;
+typedef struct QEMUTimer QEMUTimer;
+typedef void QEMUTimerCB(void *opaque);
+
+/* The real time clock should be used only for stuff which does not
+ change the virtual machine state, as it is run even if the virtual
+ machine is stopped. The real time clock has a frequency of 1000
+ Hz. */
+extern QEMUClock *rt_clock;
+
+/* Rge virtual clock is only run during the emulation. It is stopped
+ when the virtual machine is stopped. Virtual timers use a high
+ precision clock, usually cpu cycles (use ticks_per_sec). */
+extern QEMUClock *vm_clock;
+
+int64_t qemu_get_clock(QEMUClock *clock);
+
+QEMUTimer *qemu_new_timer(QEMUClock *clock, QEMUTimerCB *cb, void *opaque);
+void qemu_free_timer(QEMUTimer *ts);
+void qemu_del_timer(QEMUTimer *ts);
+void qemu_mod_timer(QEMUTimer *ts, int64_t expire_time);
+int qemu_timer_pending(QEMUTimer *ts);
+
+extern int64_t ticks_per_sec;
+extern int pit_min_timer_count;
+
+void cpu_enable_ticks(void);
+void cpu_disable_ticks(void);
+
+/* VM Load/Save */
+
+typedef FILE QEMUFile;
+
+void qemu_put_buffer(QEMUFile *f, const uint8_t *buf, int size);
+void qemu_put_byte(QEMUFile *f, int v);
+void qemu_put_be16(QEMUFile *f, unsigned int v);
+void qemu_put_be32(QEMUFile *f, unsigned int v);
+void qemu_put_be64(QEMUFile *f, uint64_t v);
+int qemu_get_buffer(QEMUFile *f, uint8_t *buf, int size);
+int qemu_get_byte(QEMUFile *f);
+unsigned int qemu_get_be16(QEMUFile *f);
+unsigned int qemu_get_be32(QEMUFile *f);
+uint64_t qemu_get_be64(QEMUFile *f);
+
+static inline void qemu_put_be64s(QEMUFile *f, const uint64_t *pv)
+{
+ qemu_put_be64(f, *pv);
+}
+
+static inline void qemu_put_be32s(QEMUFile *f, const uint32_t *pv)
+{
+ qemu_put_be32(f, *pv);
+}
+
+static inline void qemu_put_be16s(QEMUFile *f, const uint16_t *pv)
+{
+ qemu_put_be16(f, *pv);
+}
+
+static inline void qemu_put_8s(QEMUFile *f, const uint8_t *pv)
+{
+ qemu_put_byte(f, *pv);
+}
+
+static inline void qemu_get_be64s(QEMUFile *f, uint64_t *pv)
+{
+ *pv = qemu_get_be64(f);
+}
+
+static inline void qemu_get_be32s(QEMUFile *f, uint32_t *pv)
+{
+ *pv = qemu_get_be32(f);
+}
+
+static inline void qemu_get_be16s(QEMUFile *f, uint16_t *pv)
+{
+ *pv = qemu_get_be16(f);
+}
+
+static inline void qemu_get_8s(QEMUFile *f, uint8_t *pv)
+{
+ *pv = qemu_get_byte(f);
+}
+
+int64_t qemu_ftell(QEMUFile *f);
+int64_t qemu_fseek(QEMUFile *f, int64_t pos, int whence);
+
+typedef void SaveStateHandler(QEMUFile *f, void *opaque);
+typedef int LoadStateHandler(QEMUFile *f, void *opaque, int version_id);
+
+int qemu_loadvm(const char *filename);
+int qemu_savevm(const char *filename);
+int register_savevm(const char *idstr,
+ int instance_id,
+ int version_id,
+ SaveStateHandler *save_state,
+ LoadStateHandler *load_state,
+ void *opaque);
+void qemu_get_timer(QEMUFile *f, QEMUTimer *ts);
+void qemu_put_timer(QEMUFile *f, QEMUTimer *ts);
+
+/* block.c */
+typedef struct BlockDriverState BlockDriverState;
+typedef struct BlockDriver BlockDriver;
+
+extern BlockDriver bdrv_raw;
+extern BlockDriver bdrv_cow;
+extern BlockDriver bdrv_qcow;
+extern BlockDriver bdrv_vmdk;
+extern BlockDriver bdrv_cloop;
+
+void bdrv_init(void);
+BlockDriver *bdrv_find_format(const char *format_name);
+int bdrv_create(BlockDriver *drv,
+ const char *filename, int64_t size_in_sectors,
+ const char *backing_file, int flags);
+BlockDriverState *bdrv_new(const char *device_name);
+void bdrv_delete(BlockDriverState *bs);
+int bdrv_open(BlockDriverState *bs, const char *filename, int snapshot);
+int bdrv_open2(BlockDriverState *bs, const char *filename, int snapshot,
+ BlockDriver *drv);
+void bdrv_close(BlockDriverState *bs);
+int bdrv_read(BlockDriverState *bs, int64_t sector_num,
+ uint8_t *buf, int nb_sectors);
+int bdrv_write(BlockDriverState *bs, int64_t sector_num,
+ const uint8_t *buf, int nb_sectors);
+void bdrv_get_geometry(BlockDriverState *bs, int64_t *nb_sectors_ptr);
+int bdrv_commit(BlockDriverState *bs);
+void bdrv_set_boot_sector(BlockDriverState *bs, const uint8_t *data, int size);
+
+#define BDRV_TYPE_HD 0
+#define BDRV_TYPE_CDROM 1
+#define BDRV_TYPE_FLOPPY 2
+
+void bdrv_set_geometry_hint(BlockDriverState *bs,
+ int cyls, int heads, int secs);
+void bdrv_set_type_hint(BlockDriverState *bs, int type);
+void bdrv_get_geometry_hint(BlockDriverState *bs,
+ int *pcyls, int *pheads, int *psecs);
+int bdrv_get_type_hint(BlockDriverState *bs);
+int bdrv_is_removable(BlockDriverState *bs);
+int bdrv_is_read_only(BlockDriverState *bs);
+int bdrv_is_inserted(BlockDriverState *bs);
+int bdrv_is_locked(BlockDriverState *bs);
+void bdrv_set_locked(BlockDriverState *bs, int locked);
+void bdrv_set_change_cb(BlockDriverState *bs,
+ void (*change_cb)(void *opaque), void *opaque);
+void bdrv_get_format(BlockDriverState *bs, char *buf, int buf_size);
+void bdrv_info(void);
+BlockDriverState *bdrv_find(const char *name);
+void bdrv_iterate(void (*it)(void *opaque, const char *name), void *opaque);
+int bdrv_is_encrypted(BlockDriverState *bs);
+int bdrv_set_key(BlockDriverState *bs, const char *key);
+void bdrv_iterate_format(void (*it)(void *opaque, const char *name),
+ void *opaque);
+const char *bdrv_get_device_name(BlockDriverState *bs);
+
+int qcow_get_cluster_size(BlockDriverState *bs);
+int qcow_compress_cluster(BlockDriverState *bs, int64_t sector_num,
+ const uint8_t *buf);
+
+#ifndef QEMU_TOOL
+/* ISA bus */
+
+extern target_phys_addr_t isa_mem_base;
+
+typedef void (IOPortWriteFunc)(void *opaque, uint32_t address, uint32_t data);
+typedef uint32_t (IOPortReadFunc)(void *opaque, uint32_t address);
+
+int register_ioport_read(int start, int length, int size,
+ IOPortReadFunc *func, void *opaque);
+int register_ioport_write(int start, int length, int size,
+ IOPortWriteFunc *func, void *opaque);
+void isa_unassign_ioport(int start, int length);
+
+/* PCI bus */
+
+extern int pci_enabled;
+
+extern target_phys_addr_t pci_mem_base;
+
+typedef struct PCIBus PCIBus;
+typedef struct PCIDevice PCIDevice;
+
+typedef void PCIConfigWriteFunc(PCIDevice *pci_dev,
+ uint32_t address, uint32_t data, int len);
+typedef uint32_t PCIConfigReadFunc(PCIDevice *pci_dev,
+ uint32_t address, int len);
+typedef void PCIMapIORegionFunc(PCIDevice *pci_dev, int region_num,
+ uint32_t addr, uint32_t size, int type);
+
+#define PCI_ADDRESS_SPACE_MEM 0x00
+#define PCI_ADDRESS_SPACE_IO 0x01
+#define PCI_ADDRESS_SPACE_MEM_PREFETCH 0x08
+
+typedef struct PCIIORegion {
+ uint32_t addr; /* current PCI mapping address. -1 means not mapped */
+ uint32_t size;
+ uint8_t type;
+ PCIMapIORegionFunc *map_func;
+} PCIIORegion;
+
+#define PCI_ROM_SLOT 6
+#define PCI_NUM_REGIONS 7
+struct PCIDevice {
+ /* PCI config space */
+ uint8_t config[256];
+
+ /* the following fields are read only */
+ PCIBus *bus;
+ int devfn;
+ char name[64];
+ PCIIORegion io_regions[PCI_NUM_REGIONS];
+
+ /* do not access the following fields */
+ PCIConfigReadFunc *config_read;
+ PCIConfigWriteFunc *config_write;
+ int irq_index;
+};
+
+PCIDevice *pci_register_device(PCIBus *bus, const char *name,
+ int instance_size, int devfn,
+ PCIConfigReadFunc *config_read,
+ PCIConfigWriteFunc *config_write);
+
+void pci_register_io_region(PCIDevice *pci_dev, int region_num,
+ uint32_t size, int type,
+ PCIMapIORegionFunc *map_func);
+
+void pci_set_irq(PCIDevice *pci_dev, int irq_num, int level);
+
+uint32_t pci_default_read_config(PCIDevice *d,
+ uint32_t address, int len);
+void pci_default_write_config(PCIDevice *d,
+ uint32_t address, uint32_t val, int len);
+void generic_pci_save(QEMUFile* f, void *opaque);
+int generic_pci_load(QEMUFile* f, void *opaque, int version_id);
+
+extern struct PIIX3State *piix3_state;
+
+PCIBus *i440fx_init(void);
+void piix3_init(PCIBus *bus);
+void pci_bios_init(void);
+void pci_info(void);
+
+/* temporary: will be moved in platform specific file */
+PCIBus *pci_prep_init(void);
+struct openpic_t;
+void pci_pmac_set_openpic(PCIBus *bus, struct openpic_t *openpic);
+PCIBus *pci_pmac_init(void);
+
+/* openpic.c */
+typedef struct openpic_t openpic_t;
+void openpic_set_irq (openpic_t *opp, int n_IRQ, int level);
+openpic_t *openpic_init (PCIBus *bus, int *pmem_index, int nb_cpus);
+
+/* vga.c */
+
+#define VGA_RAM_SIZE (4096 * 1024)
+
+struct DisplayState {
+ uint8_t *data;
+ int linesize;
+ int depth;
+ int width;
+ int height;
+ void (*dpy_update)(struct DisplayState *s, int x, int y, int w, int h);
+ void (*dpy_resize)(struct DisplayState *s, int w, int h);
+ void (*dpy_refresh)(struct DisplayState *s);
+};
+
+static inline void dpy_update(DisplayState *s, int x, int y, int w, int h)
+{
+ s->dpy_update(s, x, y, w, h);
+}
+
+static inline void dpy_resize(DisplayState *s, int w, int h)
+{
+ s->dpy_resize(s, w, h);
+}
+
+int vga_initialize(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
+ unsigned long vga_ram_offset, int vga_ram_size);
+void vga_update_display(void);
+void vga_invalidate_display(void);
+void vga_screen_dump(const char *filename);
+
+/* vnc.c */
+void vnc_display_init(DisplayState *ds, int useAlsoSDL);
+
+/* cirrus_vga.c */
+void pci_cirrus_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base,
+ unsigned long vga_ram_offset, int vga_ram_size);
+void isa_cirrus_vga_init(DisplayState *ds, uint8_t *vga_ram_base,
+ unsigned long vga_ram_offset, int vga_ram_size);
+
+/* sdl.c */
+void sdl_display_init(DisplayState *ds, int full_screen);
+
+/* ide.c */
+#define MAX_DISKS 4
+
+extern BlockDriverState *bs_table[MAX_DISKS];
+
+void isa_ide_init(int iobase, int iobase2, int irq,
+ BlockDriverState *hd0, BlockDriverState *hd1);
+void pci_ide_init(PCIBus *bus, BlockDriverState **hd_table);
+void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table);
+int pmac_ide_init (BlockDriverState **hd_table,
+ openpic_t *openpic, int irq);
+
+/* sb16.c */
+void SB16_init (void);
+
+/* adlib.c */
+void Adlib_init (void);
+
+/* gus.c */
+void GUS_init (void);
+
+/* dma.c */
+typedef int (*DMA_transfer_handler) (void *opaque, int nchan, int pos, int size);
+int DMA_get_channel_mode (int nchan);
+int DMA_read_memory (int nchan, void *buf, int pos, int size);
+int DMA_write_memory (int nchan, void *buf, int pos, int size);
+void DMA_hold_DREQ (int nchan);
+void DMA_release_DREQ (int nchan);
+void DMA_schedule(int nchan);
+void DMA_run (void);
+void DMA_init (int high_page_enable);
+void DMA_register_channel (int nchan,
+ DMA_transfer_handler transfer_handler,
+ void *opaque);
+/* fdc.c */
+#define MAX_FD 2
+extern BlockDriverState *fd_table[MAX_FD];
+
+typedef struct fdctrl_t fdctrl_t;
+
+fdctrl_t *fdctrl_init (int irq_lvl, int dma_chann, int mem_mapped,
+ uint32_t io_base,
+ BlockDriverState **fds);
+int fdctrl_get_drive_type(fdctrl_t *fdctrl, int drive_num);
+
+/* ne2000.c */
+
+void isa_ne2000_init(int base, int irq, NetDriverState *nd);
+void pci_ne2000_init(PCIBus *bus, NetDriverState *nd);
+
+/* pckbd.c */
+
+void kbd_init(void);
+extern const char* keyboard_layout;
+
+/* mc146818rtc.c */
+
+typedef struct RTCState RTCState;
+
+RTCState *rtc_init(int base, int irq);
+void rtc_set_memory(RTCState *s, int addr, int val);
+void rtc_set_date(RTCState *s, const struct tm *tm);
+
+/* serial.c */
+
+typedef struct SerialState SerialState;
+SerialState *serial_init(int base, int irq, CharDriverState *chr);
+
+/* i8259.c */
+
+void pic_set_irq(int irq, int level);
+void pic_init(void);
+uint32_t pic_intack_read(CPUState *env);
+void pic_info(void);
+void irq_info(void);
+int pic_irq2vec(int irq);
+
+/* i8254.c */
+
+#define PIT_FREQ 1193182
+
+typedef struct PITState PITState;
+
+PITState *pit_init(int base, int irq);
+void pit_set_gate(PITState *pit, int channel, int val);
+int pit_get_gate(PITState *pit, int channel);
+int pit_get_out(PITState *pit, int channel, int64_t current_time);
+
+/* pc.c */
+void pc_init(int ram_size, int vga_ram_size, int boot_device,
+ DisplayState *ds, const char **fd_filename, int snapshot,
+ const char *kernel_filename, const char *kernel_cmdline,
+ const char *initrd_filename);
+
+/* ppc.c */
+void ppc_init (int ram_size, int vga_ram_size, int boot_device,
+ DisplayState *ds, const char **fd_filename, int snapshot,
+ const char *kernel_filename, const char *kernel_cmdline,
+ const char *initrd_filename);
+void ppc_prep_init (int ram_size, int vga_ram_size, int boot_device,
+ DisplayState *ds, const char **fd_filename, int snapshot,
+ const char *kernel_filename, const char *kernel_cmdline,
+ const char *initrd_filename);
+void ppc_chrp_init(int ram_size, int vga_ram_size, int boot_device,
+ DisplayState *ds, const char **fd_filename, int snapshot,
+ const char *kernel_filename, const char *kernel_cmdline,
+ const char *initrd_filename);
+#ifdef TARGET_PPC
+ppc_tb_t *cpu_ppc_tb_init (CPUState *env, uint32_t freq);
+#endif
+void PREP_debug_write (void *opaque, uint32_t addr, uint32_t val);
+
+extern CPUWriteMemoryFunc *PPC_io_write[];
+extern CPUReadMemoryFunc *PPC_io_read[];
+extern int prep_enabled;
+
+/* sun4m.c */
+void sun4m_init(int ram_size, int vga_ram_size, int boot_device,
+ DisplayState *ds, const char **fd_filename, int snapshot,
+ const char *kernel_filename, const char *kernel_cmdline,
+ const char *initrd_filename);
+
+/* iommu.c */
+void iommu_init(uint32_t addr);
+uint32_t iommu_translate(uint32_t addr);
+
+/* lance.c */
+void lance_init(NetDriverState *nd, int irq, uint32_t leaddr, uint32_t ledaddr);
+
+/* tcx.c */
+void tcx_init(DisplayState *ds, uint32_t addr);
+
+/* sched.c */
+void sched_init();
+
+/* magic-load.c */
+void magic_init(const char *kfn, int kloadaddr, uint32_t addr);
+
+/* timer.c */
+void timer_init(uint32_t addr, int irq);
+
+/* NVRAM helpers */
+#include "hw/m48t59.h"
+
+void NVRAM_set_byte (m48t59_t *nvram, uint32_t addr, uint8_t value);
+uint8_t NVRAM_get_byte (m48t59_t *nvram, uint32_t addr);
+void NVRAM_set_word (m48t59_t *nvram, uint32_t addr, uint16_t value);
+uint16_t NVRAM_get_word (m48t59_t *nvram, uint32_t addr);
+void NVRAM_set_lword (m48t59_t *nvram, uint32_t addr, uint32_t value);
+uint32_t NVRAM_get_lword (m48t59_t *nvram, uint32_t addr);
+void NVRAM_set_string (m48t59_t *nvram, uint32_t addr,
+ const unsigned char *str, uint32_t max);
+int NVRAM_get_string (m48t59_t *nvram, uint8_t *dst, uint16_t addr, int max);
+void NVRAM_set_crc (m48t59_t *nvram, uint32_t addr,
+ uint32_t start, uint32_t count);
+int PPC_NVRAM_set_params (m48t59_t *nvram, uint16_t NVRAM_size,
+ const unsigned char *arch,
+ uint32_t RAM_size, int boot_device,
+ uint32_t kernel_image, uint32_t kernel_size,
+ const char *cmdline,
+ uint32_t initrd_image, uint32_t initrd_size,
+ uint32_t NVRAM_image,
+ int width, int height, int depth);
+
+/* adb.c */
+
+#define MAX_ADB_DEVICES 16
+
+#define ADB_MAX_OUT_LEN 16
+
+typedef struct ADBDevice ADBDevice;
+
+/* buf = NULL means polling */
+typedef int ADBDeviceRequest(ADBDevice *d, uint8_t *buf_out,
+ const uint8_t *buf, int len);
+typedef int ADBDeviceReset(ADBDevice *d);
+
+struct ADBDevice {
+ struct ADBBusState *bus;
+ int devaddr;
+ int handler;
+ ADBDeviceRequest *devreq;
+ ADBDeviceReset *devreset;
+ void *opaque;
+};
+
+typedef struct ADBBusState {
+ ADBDevice devices[MAX_ADB_DEVICES];
+ int nb_devices;
+ int poll_index;
+} ADBBusState;
+
+int adb_request(ADBBusState *s, uint8_t *buf_out,
+ const uint8_t *buf, int len);
+int adb_poll(ADBBusState *s, uint8_t *buf_out);
+
+ADBDevice *adb_register_device(ADBBusState *s, int devaddr,
+ ADBDeviceRequest *devreq,
+ ADBDeviceReset *devreset,
+ void *opaque);
+void adb_kbd_init(ADBBusState *bus);
+void adb_mouse_init(ADBBusState *bus);
+
+/* cuda.c */
+
+extern ADBBusState adb_bus;
+int cuda_init(openpic_t *openpic, int irq);
+
+#endif /* defined(QEMU_TOOL) */
+
+/* monitor.c */
+void monitor_init(CharDriverState *hd, int show_banner);
+void term_puts(const char *str);
+void term_vprintf(const char *fmt, va_list ap);
+void term_printf(const char *fmt, ...) __attribute__ ((__format__ (__printf__, 1, 2)));
+void term_flush(void);
+void term_print_help(void);
+
+/* readline.c */
+typedef void ReadLineFunc(void *opaque, const char *str);
+
+extern int completion_index;
+void add_completion(const char *str);
+void readline_handle_byte(int ch);
+void readline_find_completion(const char *cmdline);
+const char *readline_get_history(unsigned int index);
+void readline_start(const char *prompt, int is_password,
+ ReadLineFunc *readline_func, void *opaque);
+
+/* gdbstub.c */
+
+#define DEFAULT_GDBSTUB_PORT 1234
+
+int gdbserver_start(int port);
+
+#endif /* VL_H */
--- /dev/null
+/*
+ * QEMU VNC display driver (uses LibVNCServer, based on QEMU SDL driver)
+ *
+ * Copyright (c) 2003,2004 Fabrice Bellard, Matthew Mastracci,
+ * Johannes E. Schindelin
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+#include "vl.h"
+
+#include <rfb/rfb.h>
+
+/* keyboard stuff */
+#include <rfb/keysym.h>
+#include "keysym_adapter_vnc.h"
+#include "keyboard_rdesktop.c"
+
+
+#ifndef _WIN32
+#include <signal.h>
+#endif
+
+static rfbScreenInfoPtr screen;
+static DisplayState* ds_sdl=0;
+static void* kbd_layout=0; // TODO: move into rfbClient
+
+/* mouse stuff */
+
+typedef struct mouse_magic_t {
+ /* When calibrating, mouse_calibration contains a copy of the
+ * current frame buffer. After a simulated mouse movement, the
+ * update function only gets (0,y1,width,y2) as bounding box
+ * of the changed region, so we refine that with the help of
+ * this copy, and then update the copy. */
+ char* calibration;
+ /* Mouse handling using VNC used to be wrong, because if moving the
+ * mouse very fast, the pointer got even faster. The reason for this:
+ * when the mouse sends a delta of at least 4 (Windows: 3) pixels,
+ * it is treated as if it were double the amount. I call this the
+ * sonic wall. */
+ int sonic_wall_x;
+ int sonic_wall_y;
+ /* Unfortunately, Windows and X behave differently, when the sonic
+ * wall was reached in one axis, but not the other: Windows treats
+ * them independently. I call this orthogonal. */
+ char sonic_wall_is_orthogonal;
+ /* last_dy contains the last delta sent on the y axis. We don't
+ * use the x axis (see mouse_calibration). */
+ //static int last_dy=0;
+} mouse_magic_t;
+
+mouse_magic_t* init_mouse_magic() {
+ mouse_magic_t* ret=(mouse_magic_t*)malloc(sizeof(mouse_magic_t));
+
+ ret->calibration=0;
+#ifdef EXPECT_WINDOWS_GUEST
+ ret->sonic_wall_x=3;
+ ret->sonic_wall_y=3;
+ ret->sonic_wall_is_orthogonal=1;
+#else
+ ret->sonic_wall_x=4;
+ ret->sonic_wall_y=4;
+ ret->sonic_wall_is_orthogonal=0;
+#endif
+ return ret;
+}
+
+static void vnc_save(QEMUFile* f,void* opaque)
+{
+ mouse_magic_t* s=(mouse_magic_t*)opaque;
+
+ qemu_put_be32s(f, &s->sonic_wall_x);
+ qemu_put_be32s(f, &s->sonic_wall_y);
+ qemu_put_8s(f, &s->sonic_wall_is_orthogonal);
+}
+
+static int vnc_load(QEMUFile* f,void* opaque,int version_id)
+{
+ mouse_magic_t* s=(mouse_magic_t*)opaque;
+
+ if (version_id != 1)
+ return -EINVAL;
+
+ qemu_get_be32s(f, &s->sonic_wall_x);
+ qemu_get_be32s(f, &s->sonic_wall_y);
+ qemu_get_8s(f, &s->sonic_wall_is_orthogonal);
+
+ return 0;
+}
+
+static mouse_magic_t* mouse_magic;
+
+typedef struct {
+ int x,y,w,h;
+} rectangle_t;
+/* In order to calibrate the mouse, we have to know about the bounding boxes
+ * of the last changes. */
+static rectangle_t last_update, before_update;
+static int updates_since_mouse=0;
+
+static int mouse_x,mouse_y;
+static int new_mouse_x,new_mouse_y,new_mouse_z,new_mouse_buttons;
+
+static void init_mouse(int initial_x,int initial_y) {
+ mouse_x=new_mouse_x=initial_x;
+ mouse_y=new_mouse_y=initial_y;
+ new_mouse_z=new_mouse_buttons=0;
+ mouse_magic->calibration = 0;
+}
+
+static void mouse_refresh() {
+ int dx=0,dy=0,dz=new_mouse_z;
+ static int counter=1;
+
+ counter++;
+ if(!mouse_magic->calibration && counter>=2) { counter=0; return; }
+
+ dx=new_mouse_x-mouse_x;
+ dy=new_mouse_y-mouse_y;
+
+ if(mouse_magic->sonic_wall_is_orthogonal) {
+ if(abs(dx)>=mouse_magic->sonic_wall_x) { dx/=2; mouse_x+=dx; }
+ if(abs(dy)>=mouse_magic->sonic_wall_y) { dy/=2; mouse_y+=dy; }
+ } else {
+ if(abs(dx)>=mouse_magic->sonic_wall_x || abs(dy)>=mouse_magic->sonic_wall_y) {
+ dx/=2; mouse_x+=dx;
+ dy/=2; mouse_y+=dy;
+ }
+ }
+ //fprintf(stderr,"sending mouse event %d,%d\n",dx,dy);
+ kbd_mouse_event(dx,dy,dz,new_mouse_buttons);
+ mouse_x+=dx;
+ mouse_y+=dy;
+
+ updates_since_mouse=0;
+}
+
+static int calibration_step=0;
+//static int calibration_count=0;
+
+static void mouse_find_bounding_box_of_difference(int* x,int* y,int* w,int* h) {
+ int i,j,X=*x,Y=*y,W=*w,H=*h;
+ int bpp=screen->depth/8;
+
+ *x=screen->width; *w=-*x;
+ *y=screen->height; *h=-*y;
+ for(i=X;i<X+W;i++)
+ for(j=Y;j<Y+H;j++) {
+ int offset=i*bpp+j*screen->paddedWidthInBytes;
+ if(memcmp(mouse_magic->calibration+offset,screen->frameBuffer+offset,bpp)) {
+ if(i<((*x))) { (*w)+=(*x)-i; (*x)=i; }
+ if(i>(*x)+(*w)) (*w)=i-(*x);
+ if(j<(*y)) { (*h)+=(*y)-j; (*y)=j; }
+ if(j>(*y)+(*h)) (*h)=j-(*y);
+ }
+ }
+ if(h>0)
+ memcpy(mouse_magic->calibration+Y*screen->paddedWidthInBytes,
+ screen->frameBuffer+Y*screen->paddedWidthInBytes,
+ H*screen->paddedWidthInBytes);
+}
+
+static void start_mouse_calibration() {
+ int size = screen->height*screen->paddedWidthInBytes;
+ if(mouse_magic->calibration)
+ free(mouse_magic->calibration);
+ mouse_magic->calibration = malloc(size);
+ memcpy(mouse_magic->calibration, screen->frameBuffer, size);
+ calibration_step=0;
+ // calibration_count=-1;
+ //calibration_count=1000; updates_since_mouse=1;
+ fprintf(stderr,"Starting mouse calibration:\n");
+}
+
+static void stop_mouse_calibration() {
+ if(mouse_magic->calibration)
+ free(mouse_magic->calibration);
+ mouse_magic->calibration = 0;
+}
+
+static void mouse_calibration_update(int x,int y,int w,int h) {
+ mouse_find_bounding_box_of_difference(&x,&y,&w,&h);
+ if(w<=0 || h<=0)
+ return;
+ last_update.x=x;
+ last_update.y=y;
+ last_update.w=w;
+ last_update.h=h;
+ updates_since_mouse++;
+}
+
+static void mouse_calibration_refresh() {
+ static rectangle_t cursor;
+ static int x,y;
+ static int idle_counter;
+
+ if(calibration_step==0)
+ idle_counter=0;
+ else {
+ if(updates_since_mouse==0) {
+ idle_counter++;
+ if(idle_counter>5) {
+ fprintf(stderr, "Calibration failed: no update for 5 cycles\n");
+ stop_mouse_calibration();
+ }
+ return;
+ }
+ if(updates_since_mouse!=1) {
+ fprintf(stderr,"Calibration failed: updates=%d\n",updates_since_mouse);
+ stop_mouse_calibration();
+ return;
+ }
+ }
+
+ if(calibration_step==0) {
+ x=0; y=1;
+ kbd_mouse_event(0,-1,0,0);
+ calibration_step++;
+ } else if(calibration_step==1) {
+ // find out the initial position of the cursor
+ cursor=last_update;
+ cursor.h--;
+ calibration_step++;
+ mouse_magic->sonic_wall_y=-1;
+ last_update=cursor;
+ x=0; y=2;
+ goto move_calibrate;
+ } else if(calibration_step==2) {
+ // find out the sonic_wall
+ if(last_update.y==before_update.y-2*y) {
+ mouse_magic->sonic_wall_y=y;
+ // test orthogonality
+ calibration_step++;
+ x=mouse_magic->sonic_wall_y+1; y=1;
+ goto move_calibrate;
+ } else if(last_update.y<=2) {
+ if(y<6)
+ fprintf(stderr,"Calibration failed: not enough head room!\n");
+ else
+ fprintf(stderr,"Calibration finished.\n");
+ mouse_magic->sonic_wall_x=mouse_magic->sonic_wall_y=32768;
+ goto stop_calibration;
+ } else if(last_update.y!=before_update.y-y) {
+ fprintf(stderr,"Calibration failed: delta=%d (expected: %d)\n",last_update.y-before_update.y,-y);
+ goto stop_calibration;
+ } else {
+ y++;
+move_calibrate:
+ kbd_mouse_event(-x,-y,0,0);
+ before_update=last_update;
+ }
+ } else if(calibration_step==3) {
+ if(last_update.y==before_update.y-2)
+ mouse_magic->sonic_wall_is_orthogonal=0;
+ else if(last_update.y==before_update.y-1)
+ mouse_magic->sonic_wall_is_orthogonal=-1;
+ else
+ fprintf(stderr,"Calibration failed: no clue of orthogonal.\n");
+ mouse_magic->sonic_wall_x=mouse_magic->sonic_wall_y;
+ if(last_update.x==before_update.x-mouse_magic->sonic_wall_x)
+ mouse_magic->sonic_wall_x++;
+ else if(last_update.x!=before_update.x-x*2)
+ fprintf(stderr,"Calibration failed: could not determine horizontal sonic wall x\n");
+ fprintf(stderr,"Calibration finished\n");
+stop_calibration:
+ mouse_x=last_update.x;
+ mouse_y=last_update.y;
+ stop_mouse_calibration();
+ }
+ updates_since_mouse=0;
+}
+
+/* end of mouse stuff */
+
+static void vnc_update(DisplayState *ds, int x, int y, int w, int h)
+{
+ if(ds_sdl)
+ ds_sdl->dpy_update(ds_sdl,x,y,w,h);
+ if(0) fprintf(stderr,"updating x=%d y=%d w=%d h=%d\n", x, y, w, h);
+ rfbMarkRectAsModified(screen,x,y,x+w,y+h);
+ if(mouse_magic->calibration) {
+ mouse_calibration_update(x,y,w,h);
+ }
+}
+
+#include <SDL/SDL_video.h>
+extern SDL_PixelFormat* sdl_get_format();
+
+static void vnc_resize(DisplayState *ds, int w, int h)
+{
+ int depth = screen->bitsPerPixel;
+ rfbClientIteratorPtr iter;
+ rfbClientPtr cl;
+
+ if(w==screen->width && h==screen->height)
+ return;
+
+ if(ds_sdl) {
+ SDL_PixelFormat* sdl_format;
+ ds_sdl->dpy_resize(ds_sdl,w,h);
+ ds->data = ds_sdl->data;
+ ds->linesize = screen->paddedWidthInBytes = ds_sdl->linesize;
+ screen->serverFormat.bitsPerPixel = screen->serverFormat.depth
+ = screen->bitsPerPixel = depth = ds->depth = ds_sdl->depth;
+ w = ds->width = ds_sdl->width;
+ h = ds->height = ds_sdl->height;
+ sdl_format=sdl_get_format();
+ if(sdl_format->palette==0) {
+ screen->serverFormat.trueColour=TRUE;
+ screen->serverFormat.redShift=sdl_format->Rshift;
+ screen->serverFormat.greenShift=sdl_format->Gshift;
+ screen->serverFormat.blueShift=sdl_format->Bshift;
+ screen->serverFormat.redMax=sdl_format->Rmask>>screen->serverFormat.redShift;
+ screen->serverFormat.greenMax=sdl_format->Gmask>>screen->serverFormat.greenShift;
+ screen->serverFormat.blueMax=sdl_format->Bmask>>screen->serverFormat.blueShift;
+ } else {
+ rfbColourMap* cmap=&(screen->colourMap);
+ int i;
+ screen->serverFormat.trueColour=FALSE;
+ cmap->is16=FALSE;
+ cmap->count=sdl_format->palette->ncolors;
+ if(cmap->data.bytes==0)
+ cmap->data.bytes=malloc(256*3);
+ for(i=0;i<cmap->count;i++) {
+ cmap->data.bytes[3*i+0]=sdl_format->palette->colors[i].r;
+ cmap->data.bytes[3*i+1]=sdl_format->palette->colors[i].g;
+ cmap->data.bytes[3*i+2]=sdl_format->palette->colors[i].b;
+ }
+ }
+ } else {
+ ds->data = (unsigned char*)realloc(ds->data, w*h*depth/8);
+ ds->linesize = screen->paddedWidthInBytes = w*2;
+ ds->width = w;
+ ds->height = h;
+ ds->depth = depth;
+ screen->paddedWidthInBytes = w*depth/8;
+ }
+ screen->frameBuffer = ds->data;
+
+ screen->width = w;
+ screen->height = h;
+
+ iter=rfbGetClientIterator(screen);
+ while((cl=rfbClientIteratorNext(iter)))
+ if(cl->useNewFBSize)
+ cl->newFBSizePending = TRUE;
+ else
+ rfbLog("Warning: Client %s does not support NewFBSize!\n",cl->host);
+ rfbReleaseClientIterator(iter);
+
+ if(mouse_magic->calibration) {
+ fprintf(stderr,"Warning: mouse calibration interrupted by video mode change\n");
+ stop_mouse_calibration();
+ }
+ init_mouse(w/2,h/2);
+}
+
+static void vnc_process_key(rfbBool down, rfbKeySym keySym, rfbClientPtr cl)
+{
+ static int magic=0; // Ctrl+Alt starts calibration
+
+ if(is_active_console(vga_console)) {
+ WORD keycode=keysym2scancode(kbd_layout, keySym);
+ if(keycode>=0x80)
+ keycode=(keycode<<8)^0x80e0;
+ while(keycode!=0) {
+ kbd_put_keycode((keycode&0xff)|(down?0:0x80));
+ keycode>>=8;
+ }
+ } else if(down) {
+ kbd_put_keysym(keySym);
+ }
+ if(down) {
+ if(keySym==XK_Control_L)
+ magic|=1;
+ else if(keySym==XK_Alt_L)
+ magic|=2;
+ } else {
+ if((magic&3)==3) {
+ switch(keySym) {
+ case XK_Control_L:
+ magic&=~1;
+ break;
+ case XK_Alt_L:
+ magic&=~2;
+ break;
+ case XK_m:
+ magic=0;
+ start_mouse_calibration();
+ break;
+ case XK_1 ... XK_9:
+ magic=0;
+ fprintf(stderr,"switch to %d\n",keySym-XK_1);
+ console_select(keySym - XK_1);
+ if (is_active_console(vga_console)) {
+ /* tell the vga console to redisplay itself */
+ vga_invalidate_display();
+ vnc_update(0,0,0,screen->width,screen->height);
+ }
+ break;
+ }
+ }
+ }
+}
+
+static void vnc_process_mouse(int buttonMask, int x, int y, rfbClientPtr cl)
+{
+ new_mouse_x=x; new_mouse_y=y; new_mouse_buttons=0;
+ if(buttonMask&1) new_mouse_buttons|=MOUSE_EVENT_LBUTTON;
+ if(buttonMask&2) new_mouse_buttons|=MOUSE_EVENT_MBUTTON;
+ if(buttonMask&4) new_mouse_buttons|=MOUSE_EVENT_RBUTTON;
+ if(buttonMask&8) new_mouse_z--;
+ if(buttonMask&16) new_mouse_z++;
+}
+
+ static void vnc_refresh(DisplayState *ds) {
+ if(ds_sdl)
+ ds_sdl->dpy_refresh(ds_sdl);
+ else
+ vga_update_display();
+ rfbProcessEvents(screen,0);
+ if(mouse_magic->calibration) {
+ mouse_calibration_refresh();
+ } else {
+ mouse_refresh();
+ }
+ }
+
+static void vnc_cleanup(void)
+{
+ rfbScreenCleanup(screen);
+}
+
+void vnc_display_init(DisplayState *ds, int useAlsoSDL)
+{
+ if(!keyboard_layout) {
+ fprintf(stderr, "No keyboard language specified\n");
+ exit(1);
+ }
+
+ kbd_layout=init_keyboard_layout(keyboard_layout);
+ if(!kbd_layout) {
+ fprintf(stderr, "Could not initialize keyboard\n");
+ exit(1);
+ }
+
+ mouse_magic=init_mouse_magic();
+ register_savevm("vnc", 0, 1, vnc_save, vnc_load, mouse_magic);
+
+ rfbLog=rfbErr=term_printf;
+ screen=rfbGetScreen(0,0,0,0,5,3,2);
+ if(screen==0) {
+ fprintf(stderr, "Could not initialize VNC - exiting\n");
+ exit(1);
+ }
+
+ screen->serverFormat.redShift = 11;
+ screen->serverFormat.greenShift = 5;
+ screen->serverFormat.blueShift = 0;
+ screen->serverFormat.redMax = 31;
+ screen->serverFormat.greenMax = 63;
+ screen->serverFormat.blueMax = 31;
+
+ if(useAlsoSDL) {
+ ds_sdl=(DisplayState*)malloc(sizeof(DisplayState));
+ sdl_display_init(ds_sdl,0);
+ screen->frameBuffer = ds_sdl->data;
+ } else
+ screen->frameBuffer = malloc(640*400*2);
+
+ screen->desktopName = "QEMU/VNC";
+ screen->cursor = 0;
+ screen->kbdAddEvent = vnc_process_key;
+ screen->ptrAddEvent = vnc_process_mouse;
+ rfbInitServer(screen);
+
+ vnc_resize(ds,640,400);
+
+ ds->dpy_update = vnc_update;
+ ds->dpy_resize = vnc_resize;
+ ds->dpy_refresh = vnc_refresh;
+
+ atexit(vnc_cleanup);
+}
+